<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.2">
  <link rel="apple-touch-icon" sizes="180x180" href="/xiaoshihd/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/xiaoshihd/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/xiaoshihd/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/xiaoshihd/images/logo.svg" color="#222">

<link rel="stylesheet" href="/xiaoshihd/css/main.css">


<link rel="stylesheet" href="/xiaoshihd/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"xiaoshihd.gitee.io","root":"/xiaoshihd/","scheme":"Muse","version":"7.8.0","exturl":false,"sidebar":{"position":"right","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta property="og:type" content="website">
<meta property="og:title" content="小师的Blog">
<meta property="og:url" content="http://xiaoshihd.gitee.io/xiaoshihd/index.html">
<meta property="og:site_name" content="小师的Blog">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="XiaoShi">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="http://xiaoshihd.gitee.io/xiaoshihd/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : true,
    isPost : false,
    lang   : 'zh-CN'
  };
</script>

  <title>小师的Blog</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<style>.darkmode--activated{--body-bg-color:#282828;--content-bg-color:#333;--card-bg-color:#555;--text-color:#ccc;--blockquote-color:#bbb;--link-color:#ccc;--link-hover-color:#eee;--brand-color:#ddd;--brand-hover-color:#ddd;--table-row-odd-bg-color:#282828;--table-row-hover-bg-color:#363636;--menu-item-bg-color:#555;--btn-default-bg:#222;--btn-default-color:#ccc;--btn-default-border-color:#555;--btn-default-hover-bg:#666;--btn-default-hover-color:#ccc;--btn-default-hover-border-color:#666;--highlight-background:#282b2e;--highlight-foreground:#a9b7c6;--highlight-gutter-background:#34393d;--highlight-gutter-foreground:#9ca9b6}.darkmode--activated img{opacity:.75}.darkmode--activated img:hover{opacity:.9}.darkmode--activated code{color:#69dbdc;background:0 0}button.darkmode-toggle{z-index:9999}.darkmode-ignore,img{display:flex!important}</style></head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/xiaoshihd/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">小师的Blog</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/xiaoshihd/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/xiaoshihd/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/xiaoshihd/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/xiaoshihd/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content index posts-expand">
            
      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://xiaoshihd.gitee.io/xiaoshihd/2022/04/22/%E5%9C%B0%E5%9B%BE%E6%9C%8D%E5%8A%A1%E5%8F%91%E5%B8%83/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/xiaoshihd/images/xiaoshi.png">
      <meta itemprop="name" content="XiaoShi">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="小师的Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/xiaoshihd/2022/04/22/%E5%9C%B0%E5%9B%BE%E6%9C%8D%E5%8A%A1%E5%8F%91%E5%B8%83/" class="post-title-link" itemprop="url">地图服务发布</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2022-04-22 17:28:14" itemprop="dateCreated datePublished" datetime="2022-04-22T17:28:14+08:00">2022-04-22</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2022-04-23 11:04:17" itemprop="dateModified" datetime="2022-04-23T11:04:17+08:00">2022-04-23</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/xiaoshihd/categories/%E5%89%8D%E7%AB%AF/" itemprop="url" rel="index"><span itemprop="name">前端</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="地图服务发布"><a href="#地图服务发布" class="headerlink" title="地图服务发布"></a>地图服务发布</h1><p>教程参考：<a target="_blank" rel="noopener" href="https://www.cnblogs.com/kkyyhh96/p/6379515.html">https://www.cnblogs.com/kkyyhh96/p/6379515.html</a></p>
<p>视频参考：<a target="_blank" rel="noopener" href="https://www.bilibili.com/video/BV1vk4y127P8">https://www.bilibili.com/video/BV1vk4y127P8</a></p>
<h2 id="PostgreSQL"><a href="#PostgreSQL" class="headerlink" title="PostgreSQL"></a>PostgreSQL</h2><p>MySQL 是最流行的关系型数据库管理系统（RDBMS）。</p>
<p>PostgreSQL 是一个免费的对象-关系数据库系统(ORDBMS)。ORDBMS是面向对象技术与传统的关系数据库相结合的产物，在原来关系数据库的基础上，增加了一些新的特性。</p>
<p>EnterpriseDB 是全球唯一一家提供基于 PostgreSQL 企业级产品与服务的厂商，在这里可以下载pg数据库。</p>
<p>下载地址：<a target="_blank" rel="noopener" href="https://www.enterprisedb.com/downloads/postgres-postgresql-downloads">https://www.enterprisedb.com/downloads/postgres-postgresql-downloads</a></p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210804152642.png" alt="image-20210804152642254" style="zoom:80%;" />

<p>下载进来是个exe可执行文件，双击运行。</p>
<p>安装过程参考：<a target="_blank" rel="noopener" href="https://www.runoob.com/postgresql/windows-install-postgresql.html">https://www.runoob.com/postgresql/windows-install-postgresql.html</a></p>
<p>（注意：安装时可以选择中文，但是我的报错了<code>The database cluster initialization failed</code>）</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210804212205.png" alt="image-20210804212205842" style="zoom:80%;" />

<p>汉化：</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210805095605.png" alt="image-20210805095604949" style="zoom:80%;" />

<p>安装完成后Navicat连接，密码为安装时设置的密码（xiaoshi）。</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210804154704.png" alt="image-20210804154704044" style="zoom:80%;" />

<p>默认是开机启动服务，如果需要设置成手动，按如下步骤执行：开始-&gt;运行-&gt;（然后键入：） services.msc。当您看到PostgresSQL服务时，将它们设置为手动而不是自动。</p>
<p>之后开启关闭服务可以通过如下命令：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">net start postgresql-x64-10</span><br><span class="line"></span><br><span class="line">net stop postgresql-x64-10</span><br></pre></td></tr></table></figure>

<h2 id="PostGIS"><a href="#PostGIS" class="headerlink" title="PostGIS"></a>PostGIS</h2><p>PostGIS 是一个开源程序，它<strong>为对象－关系型数据库PostgreSQL提供了存储空间地理数据的支持，使PostgreSQL成为了一个空间数据库</strong>，能够进行空间数据管理、数量测量与几何拓扑分析。PostGIS 实现了开放地理空间协会所提出的基本要素类（点、线、面、多点、多线、多面等）的SQL实现参考。 </p>
<p>PostgreSQL安装完成后自带了Application Stack Builder，但速度比较慢，而且可能会卡死无响应（我就卡死了，下载不进来）。</p>
<p>推荐直接下载exe可执行文件安装。</p>
<p>下载地址：<a target="_blank" rel="noopener" href="http://download.osgeo.org/postgis/windows/pg10/">http://download.osgeo.org/postgis/windows/pg10/</a></p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210804155233.png" alt="image-20210804155233170" style="zoom:80%;" />

<p>下载完成后安装，注意在设置安装组件时，最好选择”<strong>Create spatial database</strong>“，以便在创建数据库时可以以此作为模板。对于其他步骤的设置都选择默认值即可。</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210804155357.png" alt="image-20210804155357258" style="zoom:80%;" />

<p>输入密码：2</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210804155542.png" alt="image-20210804155541958" style="zoom:80%;" />

<p>安装成功后就可以在Navicat里面看到新增了一个数据库。</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210804160203.png" alt="image-20210804160203816" style="zoom:80%;" />

<h3 id="创建空间数据库"><a href="#创建空间数据库" class="headerlink" title="创建空间数据库"></a>创建空间数据库</h3><p>新建一个数据库postgis_test，里面新建查询，输入以下查询语句以加载<strong>PostGIS空间扩展</strong>：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> EXTENSION postgis;</span><br></pre></td></tr></table></figure>

<p>成功后，刷新，数据表中会出现spatial_ref_sys表，说明可以导入空间数据了。</p>
<p>也可以通过运行PostGIS函数来确认是否在数据库中安装了PostGIS扩展插件：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> postgis_full_version();</span><br></pre></td></tr></table></figure>

<h3 id="加载空间数据"><a href="#加载空间数据" class="headerlink" title="加载空间数据"></a>加载空间数据</h3><p>参考教程：<a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/62160223">https://zhuanlan.zhihu.com/p/62160223</a></p>
<p><a href="https://link.zhihu.com/?target=http://s3.cleverelephant.ca/postgis-workshop-2018.zip">数据下载地址</a></p>
<p>使用的数据介绍：<a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/62337014">https://zhuanlan.zhihu.com/p/62337014</a></p>
<ol>
<li> 一个shapfile必须有的文件：</li>
</ol>
<ul>
<li><p>.shp —— 存储地理要素的几何信息</p>
</li>
<li><p>.shx —— 存储要素几何图形的索引信息</p>
</li>
<li><p>.dbf —— 存储地理要素的属性信息（非几何信息）</p>
</li>
</ul>
<p>可选文件包括：</p>
<ul>
<li>.prj —— 存储空间参考信息，即地理坐标系统信息和投影坐标系统信息。使用well-known文本格式进行描述。</li>
</ul>
<p>PostGIS shapefile工具将shapefile数据从二进制转换为一系列的SQL命令，然后在数据库中运行以加载数据，从而使shapefile数据在PostGIS中可用。</p>
<ol start="2">
<li>“SRID”表示“Spatial Reference IDentifier（空间参考标识符)”。它定义了我们数据的<strong>地理坐标系统</strong>和<strong>投影</strong>的所有参数。</li>
</ol>
<p>SRID很方便，因为它将有关地图投影的所有信息（可能非常复杂）打包（更具体的说应该是映射）到一个数字中。</p>
<p>直接在PostGIS内部对spatial_ref_sys表进行查询：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> srtext <span class="keyword">FROM</span> spatial_ref_sys <span class="keyword">WHERE</span> srid <span class="operator">=</span> <span class="number">26918</span>;</span><br></pre></td></tr></table></figure>

<p>PostGIS的spatial_ref_sys表是一个OGC标准表，用于定义数据库已知的所有空间参考系统。PostGIS附带的数据列出了3000多个已知的空间参考系统以及在它们之间进行转换/重新投影所需的详细信息。</p>
<p>26918对应的空间参考系统的文本表示：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">PROJCS[</span><br><span class="line">  &quot;NAD83 / UTM zone 18N&quot;,</span><br><span class="line">  GEOGCS[</span><br><span class="line">    &quot;NAD83&quot;,</span><br><span class="line">    DATUM[</span><br><span class="line">      &quot;North_American_Datum_1983&quot;,</span><br><span class="line">      SPHEROID[</span><br><span class="line">        &quot;GRS 1980&quot;,<span class="number">6378137</span>,<span class="number">298.257222101</span>,AUTHORITY[&quot;EPSG&quot;,&quot;7019&quot;]</span><br><span class="line">      ],</span><br><span class="line">      AUTHORITY[&quot;EPSG&quot;,&quot;6269&quot;]</span><br><span class="line">    ],</span><br><span class="line">    PRIMEM[&quot;Greenwich&quot;,<span class="number">0</span>,AUTHORITY[&quot;EPSG&quot;,&quot;8901&quot;]],</span><br><span class="line">    UNIT[&quot;degree&quot;,<span class="number">0.01745329251994328</span>,AUTHORITY[&quot;EPSG&quot;,&quot;9122&quot;]],</span><br><span class="line">    AUTHORITY[&quot;EPSG&quot;,&quot;4269&quot;]</span><br><span class="line">  ],</span><br><span class="line">  UNIT[&quot;metre&quot;,<span class="number">1</span>,AUTHORITY[&quot;EPSG&quot;,&quot;9001&quot;]],</span><br><span class="line">  PROJECTION[&quot;Transverse_Mercator&quot;],</span><br><span class="line">  <span class="keyword">PARAMETER</span>[&quot;latitude_of_origin&quot;,<span class="number">0</span>],</span><br><span class="line">  <span class="keyword">PARAMETER</span>[&quot;central_meridian&quot;,<span class="number">-75</span>],</span><br><span class="line">  <span class="keyword">PARAMETER</span>[&quot;scale_factor&quot;,<span class="number">0.9996</span>],</span><br><span class="line">  <span class="keyword">PARAMETER</span>[&quot;false_easting&quot;,<span class="number">500000</span>],</span><br><span class="line">  <span class="keyword">PARAMETER</span>[&quot;false_northing&quot;,<span class="number">0</span>],</span><br><span class="line">  AUTHORITY[&quot;EPSG&quot;,&quot;26918&quot;],</span><br><span class="line">  AXIS[&quot;Easting&quot;,EAST],</span><br><span class="line">  AXIS[&quot;Northing&quot;,NORTH]</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<p> 如果从数据的data目录打开xxx.prj文件，将看到相同的投影信息。</p>
<p>使用PostGIS的一个常见问题是弄清楚要使用哪个SRID号来使用他们的数据。他们只有一个.prj文件，但是应该如何将.prj文件转换成正确的SRID号呢？</p>
<p>最简单的方法就是去GIS软件里面查看shapfile的属性。</p>
<p>加载过程：</p>
<p>使用<strong>PostGIS 2.0 Shapefile and DBF Loader Exporter</strong>进行加载。</p>
<ol>
<li>设置连接</li>
</ol>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210805144708.png" alt="image-20210805144708038" style="zoom:80%;" />

<ol start="2">
<li>导入数据，设置SRID号</li>
</ol>
<p>在QGIS里面查看SRID为<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210805145010.png" alt="image-20210805145010252" style="zoom:80%;" />。</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210805150251.png" alt="image-20210805150251816" style="zoom:80%;" />

<p>可以看到，导入失败，报错：<code>Unable to convert data value to UTF-8 (iconv reports &quot;Illegal byte sequence&quot;). Current encoding is &quot;UTF-8&quot;. Try &quot;LATIN1&quot; (Western European), or one of the values described at http://www.postgresql.org/docs/current/static/multibyte.html.</code></p>
<p>原因是编码格式不对，打开Options 将编码改为 GBK （中文），如果改成GBK还不行，试试gb18030编码。</p>
<h3 id="数据详解"><a href="#数据详解" class="headerlink" title="数据详解"></a>数据详解</h3><p>数据是有关纽约市的四个shapefile文件和一个包含社会人口经济数据的数据表。</p>
<ol>
<li>nyc_census_blocks</li>
</ol>
<h2 id="QGIS"><a href="#QGIS" class="headerlink" title="QGIS"></a>QGIS</h2><p>QGIS教程：<a target="_blank" rel="noopener" href="https://www.osgeo.cn/qgis-tutorial/index.html">https://www.osgeo.cn/qgis-tutorial/index.html</a></p>
<p>QGIS，是一个桌面端GIS查看器/编辑器，用于快速查看数据。</p>
<p>QGIS可以查看许多数据格式，包括shapefile和PostGIS数据库。</p>
<p>QGIS，是一个桌面端GIS查看器/编辑器，用于快速查看数据。</p>
<p>QGIS可以查看许多数据格式，包括shapefile和PostGIS数据库。</p>
<p>它的图形界面允许我们轻松探索我们的数据，以及快速的对地理要素样式进行设置。</p>
<p>下载地址：<a target="_blank" rel="noopener" href="https://qgis.org/en/site/forusers/download.html">https://qgis.org/en/site/forusers/download.html</a></p>
<p>对于新用户，推荐独立安装程序。</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210804230604.png" alt="image-20210804230604759" style="zoom:80%;" />

<p>汉化：</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210805095200.png" alt="image-20210805095200735" style="zoom:80%;" />

<p>安装完成之后可以连接postgreSQL数据直接查看数据：</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210804232220.png" alt="image-20210804232220609" style="zoom:80%;" />

<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210804232313.png" alt="image-20210804232313533" style="zoom:80%;" />

<p>在这张图右下角可以看到使用的坐标系统SRID号为26918。</p>
<h2 id="GeoServer"><a href="#GeoServer" class="headerlink" title="GeoServer"></a>GeoServer</h2><p>GeoServer教程：<a target="_blank" rel="noopener" href="https://ethanblog.com/tech/installation-of-geoserver.html">https://ethanblog.com/tech/installation-of-geoserver.html</a></p>
<p>GeoServer的是一个基于Java的软件，它允许用户查看和编辑地理空间数据，使用开放地理空间联盟（OGC）提出的开放标准，为地图创建和数据分享提供了强大的便利性。</p>
<p>GeoServer是OpenGIS Web 服务器规范的 J2EE 实现，利用 GeoServer 可以方便的发布地图数据，允许用户对特征数据进行更新、删除、插入操作，通过 GeoServer 可以比较容易的在用户之间迅速共享空间地理信息。</p>
<p>主要特性：</p>
<p>兼容 WMS 和 WFS 特性；支持 PostGIS 、 Shapefile 、 ArcSDE 、 Oracle 、 VPF 、  MySQL 、 MapInfo ；支持上百种投影；能够将网络地图输出为 jpeg 、 gif 、 png 、 SVG 、 KML  等格式；能够运行在任何基于 J2EE/Servlet 容器之上；嵌入 MapBuilder 支持 AJAX  的地图客户端OpenLayers；除此之外还包括许多其他的特性。</p>
<p>下载地址：<a target="_blank" rel="noopener" href="http://geoserver.org/release/2.19.0/">http://geoserver.org/release/2.19.0/</a></p>
<p>下载进来是一个war包，放到Tomcat里面即可启动服务。</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210804145336.png" alt="image-20210804145336531" style="zoom:80%;" />

<p>启动后，访问地址<a target="_blank" rel="noopener" href="http://localhost:8080/geoserver/%E3%80%82">http://localhost:8080/geoserver/。</a></p>
<p>这时可以设置GeoServer的管理员帐号。帐号admin，密码geoserver。当出现下图时，说明服务器配置成功。</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210804233112.png" alt="image-20210804233112513" style="zoom:80%;" />

<p>该图即为GeoServer在服务器上的首页。可以在本页进行数据的连接和发布。</p>
<p>首先，数据区域集中展示了GeoServer服务器上的所有数据和工作区划分，提供数据存储、图层预览、样式编辑等功能。数据区域是我们在实际开发中需要重点关注的地方。</p>
<ul>
<li>图层预览提供了GeoServer的所图层配置列表，并提供以各种格式预览。在以后我们继续深入学习后，发布了某一个图层可以来到这里选择进行预览。</li>
<li>工作区类似我们工作空间，概念可以类比我们进行其他开发时所配置的项目根目录，用于对某一项具体的工作进行统一的管理。对应于GeoServer所用于的web服务，也可以理解为是一个web网站的根目录。</li>
<li>数据存储用于管理GeoServer的数据存储，我们可以将其理解为为Web服务提供数据支持的“数据库”。</li>
<li>图层和图层组都是用来发布和管理新图层，并使用组的形式来进行组织和管理。</li>
<li>styles是用于管理GeoServer发布的样式。</li>
</ul>
<p>服务部分主要是面向高级用户的，他们可以在此修改GeoServer提供的请求协议的配置。</p>
<ul>
<li>Web Coverage Service (WCS)用于管理元数据信息和WCS、WFS、WMS通用的配置信息，如数据请求读写最大值等。</li>
<li>Web Feature Service (WFS)用于配置和管理Feature Data、服务级别以及GML输出等。</li>
<li>Web Map Service (WMS)用于管理和配置栅格数据和SVG选项以及切片地图压缩和分级情况。</li>
</ul>
<h3 id="数据发布"><a href="#数据发布" class="headerlink" title="数据发布"></a>数据发布</h3><p>在GeoServer上部署地图数据非常简单，GeoServer支持的数据格式和数据源也很多，发布和部署地图数据涉及到GeoServer的几个重要知识点：<strong>工作区</strong>、<strong>数据存储</strong>和<strong>图层</strong>等概念。</p>
<ol>
<li>进入GeoServer首页，点击左侧的工作区（Workspaces），再点击添加新的工作区（Add new workspaces）可以创建工作空间。工作空间的作用是在于将不同数据来源的数据保存在一起。在设置URI时，须设置为<code>http://localhost:8080/china</code>，china代表的是工作空间的名字，这样所有与之相关的网页均在这个URI之后。</li>
</ol>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210805150914.png" alt="image-20210805150914247" style="zoom:80%;" />

<ol start="2">
<li><p>接下来点击数据存储（Stores），再点击添加新的数据存储（Add new store），可以添加一个新的数据源。GeoServer支持多种数据类型。在这里我们以PostGIS为例进行服务的发布。</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210806131553.png" alt="image-20210806131553756" style="zoom:80%;" />

<p>首先点击PostGIS选项，进入数据源信息的页面。先点击工作区（Workspace）下拉选项，可以选择具体的工作空间，例如本文中选择china。</p>
<p>接下来输入数据源名称，这是标识不同数据的依据，例如本文中输入gdp。</p>
<p>在连接参数中，输入host为localhost，端口5432，再输入数据源在PostgreSQL中的数据库名称，之后输入连接PostgreSQL的帐号和密码即可完成数据库的连接。</p>
<p>在最下面点击保存即可。</p>
</li>
</ol>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210805151308.png" alt="image-20210805151308547" style="zoom:80%;" />

<ol start="3">
<li>接下来就要发布具体的图层了。点击图层（Layers），即可进入图层选择界面；再点击添加一个新图层（Add a new  resource），即可发布具体的图层。点击后，先选择具体的数据源，会出现该数据源下的各种表，选择需要发布为图层的数据表，点击发布（publish），即可进行发布。</li>
</ol>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210805151504.png" alt="image-20210805151504094" style="zoom:80%;" />

<p>可以根据需要输入图层名称，也可以直接使用默认的图层名称。需要注意的是地图投影的定义：</p>
<p>在这里可以输入地图投影。如果原图没有投影，将不会进行显示，在这里可以点击Find，输入投影的代码（如WGS84为4326）进行查找。接下来在下方的范围中，点击从数据中计算（Compute from data），即可算出范围。</p>
<p>其他的文本框可以不填。保存之后即为图层的发布。</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210805151923.png" alt="image-20210805151806217" style="zoom:80%;" />

<ol start="3">
<li>为了查看发布后的效果，可以点击左侧的Layer Preview，找到刚刚发布的内容。GeoServer提供了多种数据格式可以调用。点击OpenLayers可以直接看到使用OpenLayers调用的图层。</li>
</ol>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210805153625.png" alt="image-20210805153625854" style="zoom: 67%;" />

<h3 id="服务发布"><a href="#服务发布" class="headerlink" title="服务发布"></a>服务发布</h3><p>OGC（Open Geospatial Consortium，开放地理信息协会）是一个非赢利的国际化标准制定组织，领导进行对地理数据相关的操作和服务标准的制定。</p>
<p>Web Services 即 Web 服务，它是自包含的、模块化的应用程序，它可以在网络中被描述、发布、查找以及调用。Web  服务的一个主要思想，就是未来的应用将由一组应用了网络的服务组合而成。在 Web Services 体系中，所有东西都是服务，这些服务发布一个  API 供网络中的其他服务或者应用使用，并且封装了实现细节。Web Services 是 OGC  规范以及建立面向服务的空间共享体系的基础技术体系。空间信息 Web 服务是在 Web  服务技术和标准基础之上实现的地理空间信息网上在线服务。它利用 Web  服务技术提供的公共接口、交换协议和服务规范，提供应用客户管理、注册服务、编码、处理服务、描述服务和数据服务等。主要的应用客户包括发现客户、地图浏览客户、影像利用客户等。空间信息 Web 服务除了采用基本的 Web 服务技术协议外，还需要相关地理空间信息及处理的技术协议，目前主要有 OGC、ISO/TC211 和 W3C 等组织在进行相关协议标准的制定。 OGC Web 服务（OWS）即是典型的空间信息 Web 服务标准体系。</p>
<p>OGC Web 服务公共执行规范详细描述了 OWS 接口执行规范包含的公共方面：</p>
<ul>
<li>操作请求和响应的内容</li>
<li>操作请求和响应包含的参数和数据结构</li>
<li>操作请求和响应的 XML 和 KVP 编码</li>
</ul>
<p>OGC 服务类型：</p>
<ul>
<li><p>Web 地图服务 (<strong>WMS</strong>，Web Map Service)，用于以<strong>地图图像</strong>的形式提供图层集合</p>
<p>Web 地图服务（WMS）利用具有地理空间位置信息的数据制作地图。在 WMS 规范中将地图定义为地理数据可视的表现，WMS 返回的不是地图数据，而是地图图像。</p>
</li>
<li><p><strong>TMS</strong> 切片地图服务 (Tile map Servcie)定义了一些操作，这些操作允许用户按需访问切片地图，访问速度更快，还支持修改坐标系。</p>
<p>切片地图服务又叫缓存服务区，地图缓存是使地图和图像服务更快运行的一种非常有效的方法。创建地图缓存时，服务器会在若干个不同的比例级别上绘制整个地图并存储地图图像的副本。然后，服务器可在用户请求使用地图时分发这些图像。对于服务器来说，每次请求使用地图时，返回缓存的图像要比绘制地图快得多。</p>
<p>切片地图服务的优点：</p>
<ol>
<li>由于切片地图服务中的瓦片不需要服务器实时生成，本身存在服务器的硬盘上，所以大大提高了服务器的性能。</li>
<li>瓦片图片的详细程度不会对服务器分发副本的速度造成显著影响。</li>
</ol>
<p>切片服务的缺点：</p>
<ol>
<li>切片地图服务由于瓦片图片已经存在，所以该服务实现的功能有限，无法对图层进行一系列操作。</li>
<li>当缓存级别较高时，占用的硬盘存储量较大。</li>
</ol>
</li>
<li><p>Web 地图切片服务 (<strong>WMTS</strong>，Web Map Tile Service)，用于以缓存地图切片的形式提供地图图层</p>
<p>WMTS的目的是，更高效快速的加载渲染地图数据。如果海量的地图数据以矢量的形式传输到客户端，在客户端渲染，首先需要消耗大量的网络流量，其次对客户端的CPU也是很大的负荷。考虑到这些情况，WMTS提出预渲染图块的模式，在服务端将地图渲染好，并根据比例尺分割不同的栅格图块，根据客户端的请求，传输这些图块，提供给客户端显示。</p>
<p>目前，大部分PC端、手机端的地图底图使用的都是这种<strong>栅格瓦片</strong>。</p>
<p>TMS和WMTS差异主要在于协议、瓦片组织方式，WMTS理论模型更好，TMS来自于OSGeo，WMTS来自于OGC。</p>
</li>
<li><p>Web 要素服务 (<strong>WFS</strong>，Web Feature Service)，用于以<strong>矢量要素</strong>的形式提供数据</p>
<p>WFS 是基于地理要素级别的数据共享和数据操作，WFS 规范定义了若干基于地理要素（Feature）级别的数据操作接口，并以 HTTP  作为分布式计算平台。通过 WFS 服务，客户端可以得到矢量数据格式描述的单个地理要素的空间数据或要素集的空间数据，并可以对单个地理要素进行编辑、 删除、 添加等数据操作。WFS 采用 GML 描述地理要素特征， 根据用户请求的内容返回 GML 描述的空间数据。</p>
</li>
<li><p>Web 覆盖服务 (<strong>WCS</strong>，Web Coverage Service)，网络覆盖服务是面向空间影像数据，它将包含地理位置的地理空间数据作为”覆盖（Coverage）”在网上相互交换，如卫星影像、数字高程数据等栅格数据。</p>
<p>WCS 面向空间影像数据，它将包含地理位置值的地理空间数据作为 “覆盖物（COverage）“在网上相互交换。</p>
</li>
<li><p>Web 处理服务 (<strong>WPS</strong>，Web Processing Server)，用于提供地理空间处理功能</p>
</li>
</ul>
<p>可提供 OGC 功能：</p>
<table>
<thead>
<tr>
<th>服务类型</th>
<th>WCS</th>
<th>WFS</th>
<th>WMS</th>
<th>WMTS</th>
<th>WPS</th>
</tr>
</thead>
<tbody><tr>
<td>地图服务</td>
<td><img src="https://enterprise.arcgis.com/zh-cn/server/latest/publish-services/linux/GUID-C37FC3E5-A40B-418A-9F4A-1765E05D2358-web.png" alt="支持"></td>
<td><img src="https://enterprise.arcgis.com/zh-cn/server/latest/publish-services/linux/GUID-C37FC3E5-A40B-418A-9F4A-1765E05D2358-web.png" alt="支持"></td>
<td><img src="https://enterprise.arcgis.com/zh-cn/server/latest/publish-services/linux/GUID-C37FC3E5-A40B-418A-9F4A-1765E05D2358-web.png" alt="支持"></td>
<td><img src="https://enterprise.arcgis.com/zh-cn/server/latest/publish-services/linux/GUID-C37FC3E5-A40B-418A-9F4A-1765E05D2358-web.png" alt="支持"></td>
<td></td>
</tr>
<tr>
<td>地理数据服务</td>
<td><img src="https://enterprise.arcgis.com/zh-cn/server/latest/publish-services/linux/GUID-C37FC3E5-A40B-418A-9F4A-1765E05D2358-web.png" alt="支持"></td>
<td><img src="https://enterprise.arcgis.com/zh-cn/server/latest/publish-services/linux/GUID-C37FC3E5-A40B-418A-9F4A-1765E05D2358-web.png" alt="支持"></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>影像服务</td>
<td><img src="https://enterprise.arcgis.com/zh-cn/server/latest/publish-services/linux/GUID-C37FC3E5-A40B-418A-9F4A-1765E05D2358-web.png" alt="支持"></td>
<td></td>
<td><img src="https://enterprise.arcgis.com/zh-cn/server/latest/publish-services/linux/GUID-C37FC3E5-A40B-418A-9F4A-1765E05D2358-web.png" alt="支持"></td>
<td><img src="https://enterprise.arcgis.com/zh-cn/server/latest/publish-services/linux/GUID-C37FC3E5-A40B-418A-9F4A-1765E05D2358-web.png" alt="支持"></td>
<td></td>
</tr>
<tr>
<td>地理处理服务</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td><img src="https://enterprise.arcgis.com/zh-cn/server/latest/publish-services/linux/GUID-C37FC3E5-A40B-418A-9F4A-1765E05D2358-web.png" alt="支持"></td>
</tr>
</tbody></table>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/Tmraz/article/details/108749365?utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-8.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-8.control">三种服务参数详解</a></p>
<h4 id="WMS服务"><a href="#WMS服务" class="headerlink" title="WMS服务"></a>WMS服务</h4><p>GeoServer中以OpenLayers方式预览WMS服务发布的地图：</p>
<ol>
<li><p>请求</p>
<figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://localhost:8088/geoserver/china/wms?service=WMS&amp;version=1.1.0&amp;request=GetMap&amp;layers=china:china_2014gdp&amp;bbox=73.441276550293,18.1598281860352,135.086944580078,53.5617713928223&amp;width=768&amp;height=441&amp;srs=EPSG:4326&amp;styles=&amp;format=application/openlayers</span><br></pre></td></tr></table></figure>

<p>响应：（一个html文件，地图外部边框）</p>
</li>
<li><p>请求：（发起者ol.js）</p>
<figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://localhost:8088/geoserver/china/wms?SERVICE=WMS&amp;VERSION=1.1.1&amp;REQUEST=GetMap&amp;FORMAT=image%2Fpng&amp;TRANSPARENT=true&amp;STYLES&amp;LAYERS=china%3Achina_2014gdp&amp;exceptions=application%2Fvnd.ogc.se_inimage&amp;SRS=EPSG%3A4326&amp;WIDTH=769&amp;HEIGHT=442&amp;BBOX=70.470703125%2C16.4619140625%2C138.005859375%2C55.2568359375</span><br></pre></td></tr></table></figure>

<p>响应：</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210806125217.png" alt="image-20210806125217252" style="zoom:80%;" /></li>
<li><p>点击地图对象的某个省份，返回属性信息。</p>
<p>请求：</p>
<figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://localhost:8088/geoserver/china/wms?SERVICE=WMS&amp;VERSION=1.1.1&amp;REQUEST=GetFeatureInfo&amp;FORMAT=image%2Fpng&amp;TRANSPARENT=true&amp;QUERY_LAYERS=china%3Achina_2014gdp&amp;STYLES&amp;LAYERS=china%3Achina_2014gdp&amp;exceptions=application%2Fvnd.ogc.se_inimage&amp;INFO_FORMAT=text%2Fhtml&amp;FEATURE_COUNT=50&amp;X=50&amp;Y=50&amp;SRS=EPSG%3A4326&amp;WIDTH=101&amp;HEIGHT=101&amp;BBOX=110.3466794192791%2C38.5839846432209%2C119.2236325442791%2C47.4609377682209</span><br></pre></td></tr></table></figure>

<p>响应：（一个html文件）</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210806125914.png" alt="image-20210806125914280" style="zoom:80%;" /></li>
</ol>
<p>WMS 规范定义了三个操作：</p>
<p>参考：<a target="_blank" rel="noopener" href="https://blog.csdn.net/drr789/article/details/8998638?utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-1.control">WMS的三大操作</a></p>
<ol>
<li><p>GetCapabilities 操作返回服务级元数据，它是对服务信息内容和请求参数的一种描述，元数据使用 XML 形式文件表示；</p>
<p>请求参数：</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210806130133.png" alt="image-20210806130133895" style="zoom:80%;" /></li>
<li><p>GetMap 操作根据客户端发出的请求参数在服务端进行检索，<strong>服务器返回一个地图图象</strong>，其地理空间参数和大小是已经明确定义的，返回的地图图象可以是 GIF，JPEG，PNG 或 SVG 格式的；</p>
<p>请求参数：</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210806130203.png" alt="image-20210806130203534" style="zoom:80%;" /></li>
<li><p>GetFeatureInfo 操作根据用户请求的 X，Y 坐标或感兴趣的图层，返回这些特殊要素的信息，信息以 HTML，GML 或者 ASCII 格式表示。</p>
<p>请求参数：</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210806130247.png" alt="image-20210806130247319" style="zoom:80%;" /></li>
</ol>
<h4 id="WFS服务"><a href="#WFS服务" class="headerlink" title="WFS服务"></a>WFS服务</h4><p>参考：<a target="_blank" rel="noopener" href="https://www.cnblogs.com/naaoveGIS/p/5508882.html">https://www.cnblogs.com/naaoveGIS/p/5508882.html</a></p>
<p> WFS，即Web要素服务，<strong>支持对地理要素的插入，更新，删除，检索和发现服务</strong>。不同于WMS（Web地图服务）的是，该服务专注于要素的地理信息，而忽略其渲染信息，简化了返回信息。</p>
<p>一个图层的WFS服务查看方法是在Layer Preview页面，选择WFS下的GeoJSON（以JSON数据形式展现要素信息，方便解析），查看该图层的要素信息。</p>
<p>一个WFS请求如下：</p>
<figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://localhost:8088/geoserver/china/ows?service=WFS&amp;version=1.0.0&amp;request=GetFeature&amp;typeName=china%3Achina_2014gdp&amp;maxFeatures=50&amp;outputFormat=application%2Fjson</span><br></pre></td></tr></table></figure>

<p><strong>GetFeature（获取图层要素）</strong></p>
<table>
<thead>
<tr>
<th><strong>参数名称</strong></th>
<th><strong>是否必须</strong></th>
<th><strong>默认值</strong></th>
<th><strong>举例</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>VERSION</strong></td>
<td>是</td>
<td>1.1.0</td>
<td>version=1.1.0或version=1.0.0</td>
</tr>
<tr>
<td><strong>SERVICE</strong></td>
<td>是</td>
<td>WFS</td>
<td>WFS</td>
</tr>
<tr>
<td><strong>REQUEST=GetFeature</strong></td>
<td>是</td>
<td></td>
<td></td>
</tr>
<tr>
<td><strong>TYPENAME</strong></td>
<td>是</td>
<td>text/xml; subtype=gml/3.1.1</td>
<td></td>
</tr>
<tr>
<td><strong>OUTPUTFORMAT</strong></td>
<td></td>
<td></td>
<td>outputFormat=GML2</td>
</tr>
</tbody></table>
<h4 id="WMTS服务"><a href="#WMTS服务" class="headerlink" title="WMTS服务"></a>WMTS服务</h4><p>Web Map Tile Service（网络地图瓦片服务），简称WMTS，由开放地理信息联盟（Open GeoSpatial Consortium，OGC）制定，是和WMS并列的重要OGC规范之一。WMTS不同于WMS,它最重要的特征是<strong>采用缓存技术能够缓解WebGIS服务器端数据处理的压力</strong>，提高交互响应速度，大幅改善在线地图应用客户端的用户体验。WMTS是OGC主推的缓存技术规范，是目前各种缓存技术相互兼容的一种方法。</p>
<p>WMTS接口支持的三类资源如下表所示：</p>
<table>
<thead>
<tr>
<th>操作</th>
<th>是否必选</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>GetCapabilities</td>
<td>是</td>
<td>获取服务的元信息</td>
</tr>
<tr>
<td>GetTile</td>
<td>是</td>
<td>获取切片</td>
</tr>
<tr>
<td>GetFeatureInfo</td>
<td>否</td>
<td>获取点选的要素信息</td>
</tr>
</tbody></table>
<p>一个WMTS请求如下：</p>
<figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://localhost:8088/geoserver/gwc/service/wmts?REQUEST=GetTile&amp;SERVICE=WMTS&amp;VERSION=1.0.0&amp;LAYER=china:china_2014gdp&amp;STYLE=&amp;TILEMATRIX=EPSG:4326:5&amp;TILEMATRIXSET=EPSG:4326&amp;FORMAT=application/vnd.mapbox-vector-tile&amp;TILECOL=48&amp;TILEROW=6</span><br></pre></td></tr></table></figure>

<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210808221539.png" alt="image-20210808221539428" style="zoom:80%;" />

<h3 id="矢量切图"><a href="#矢量切图" class="headerlink" title="矢量切图"></a>矢量切图</h3><p>矢量切片的优点是：</p>
<ul>
<li><strong>数据在客户端渲染</strong>，而不是在服务器端。这允许不同的地图应用程序使用不同的样式去渲染一个地图，而不需要事先在服务器端（比如GeoServer）进行预先的样式配置。</li>
<li><strong>矢量切片的大小通常比图片瓦片小</strong>，这可以使得数据传输得更快以及使用更低的带宽。</li>
<li>GeoServer内嵌的GeoWebCache可以有效地存储矢量切片数据。由于样式由客户端配置，而不是在服务器配置，因此<strong>GeoWebCache只需要存储一个矢量切片就能在客户端配置不同的样式</strong>。</li>
<li>由于在客户端上可以获取到矢量数据，所以<strong>不需要相应地增加带宽，就可以绘制分辨率很高的地图</strong>。</li>
<li><strong>客户端可以本地访问实际的要素信息</strong>（属性信息和几何信息），所以可以进行非常复杂和精细的要素渲染。</li>
</ul>
<p>矢量切片的主要缺点是需要对地理数据进行预处理，以便客户端能够完成所需的绘图（类似于图像瓦片地图的预处理数据）。<strong>考虑到这一点，矢量切片只能用于渲染</strong>。（虽然是矢量格式，但是它们不可编辑，矢量切片是为了读取和渲染优化的格式，如果想在客户端<strong>编辑要素，最适合的是使用OGC的WFS服务</strong>）</p>
<p><strong>GeoServer可以生成三种格式的矢量切片：GeoJSON，TopoJSON，MapBox Vector（MVT）</strong>。这些矢量切片格式也得到OpenLayers和其他客户端地图引擎的支持。</p>
<p>MVT是生产环境中首选的矢量切片格式。</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210806150032.jpg" alt="v2-993218ce2e75170788779296d67ba9ba_r" style="zoom: 80%;" />

<p>GeoServer的矢量切片插件是官方的插件，下载地址：<a target="_blank" rel="noopener" href="http://geoserver.org/release/2.19.0/%E3%80%82">http://geoserver.org/release/2.19.0/。</a></p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210806124018.png" alt="image-20210806124018279" style="zoom:80%;" />

<p>将下载的内容解压（jar包）并复制到GeoServer的WEB-INF/lib文件夹下。重新启动GeoServer。</p>
<ol>
<li><p>验证矢量切片扩展是否已安装成功：打开GeoServer的Web管理界面。单击”<strong>图层</strong>“并随意选择一个矢量图层。</p>
<p>图层类型（图层可以分为两种类型的数据：栅格和矢量）</p>
</li>
</ol>
<table>
<thead>
<tr>
<th>领域</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td><img src="http://docs.geoserver.org/stable/en/user/_images/raster_icon.png" alt="../../_images/raster_icon.png"></td>
<td>光栅（栅格）</td>
</tr>
<tr>
<td><img src="http://docs.geoserver.org/stable/en/user/_images/polygon_icon.png" alt="../../_images/polygon_icon.png"></td>
<td>多边形</td>
</tr>
<tr>
<td><img src="http://docs.geoserver.org/stable/en/user/_images/line_string_icon.png" alt="../../_images/line_string_icon.png"></td>
<td>线</td>
</tr>
<tr>
<td><img src="http://docs.geoserver.org/stable/en/user/_images/point_icon.png" alt="../../_images/point_icon.png"></td>
<td>点</td>
</tr>
</tbody></table>
<ol start="2">
<li>点击”<strong>TileCaching</strong>“面板，滚动页面到”<strong>Tile Image Formats</strong>“部分，除了标准的GIF/PNG/JPEG格式之外，看到以下内容就表示矢量切片的插件已经安装成功了。</li>
</ol>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210806150858.png" alt="image-20210806150858530" style="zoom:80%;" />

<p>勾选上面红框中的格式点击保存即可发布矢量切图服务。</p>
<ol start="3">
<li>进入Tile Layers，选择pbf预览即可预览效果：</li>
</ol>
<p><img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210808190237.png" alt="image-20210808190237522"></p>
<p>效果如下：</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210808190459.png" alt="image-20210808190459394" style="zoom:80%;" />

<p>服务地址需要到点击左上角geoserver图标退回首页，点击右侧的tms：</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210808233055.png" alt="image-20210808233025537" style="zoom:80%;" />

<p>找到发布的服务：</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210808232955.png" alt="image-20210808232955563" style="zoom:80%;" />

<h4 id="GeoWebCache"><a href="#GeoWebCache" class="headerlink" title="GeoWebCache"></a>GeoWebCache</h4><p>参考：<a target="_blank" rel="noopener" href="https://www.cnblogs.com/hao-zhang/p/10051159.html">https://www.cnblogs.com/hao-zhang/p/10051159.html</a></p>
<p>在geoserver1.7版本之后，geoserver本身集成了GeoWebCache这个模块。<strong>GeoWebCache</strong>(GWC)是一个采用Java实现用于缓存WMS（Web Map Service）Tile的开源项目。当地图客户端请求一张新地图和Tile时，GeoWebCache将拦截这些调用然后返回缓存过的Tiles。如果找不到缓存再调用服务器上的Tiles，从而提高地图展示的速度。实现更好的用户体验。 </p>
<ol>
<li>GWC支持多种来源的瓦片，比如ArcGIS的瓦片。</li>
<li>GWC支持多种请求，比如WMS、WMS-C、WMTS、TMS、Googl Maps KML和Virtual Earth。</li>
<li>GWC支持在第一次请求地图某范围时，将此范围内的地图按照配置的信息进行切图缓存。第二次同样请求此范围的地图时，直接读取缓存瓦片进行加速显示。此功能类似于AGS的动态出图。</li>
<li>GWC同时也支持预先将瓦片按照配置信息切完，地图加载时直接读取瓦片。此功能类似于AGS的瓦片缓存出图。</li>
</ol>
<p>对比两个服务的url：<br><code> http://localhost:8680/geoserver/wms</code><br><code> http://localhost:8680/geoserver/gwc/service/wms</code></p>
<p>可以看见两者的区别仅仅在于，当<strong>请求的URL中加上gwc/service后，便可以开启瓦片缓存服务</strong>了。</p>
<h3 id="跨域配置"><a href="#跨域配置" class="headerlink" title="跨域配置"></a>跨域配置</h3><p>要想外部程序能够调用地图服务，首先需要对GeoServer进行跨域配置。</p>
<p>开启<code>CORS</code>跨域请求访问的方法，即在<code>webapps/geoserver/WEB-INF/web.xml</code>中添加以下内容：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">web-app</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--...--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">filter</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">filter-name</span>&gt;</span>CorsFilter<span class="tag">&lt;/<span class="name">filter-name</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">filter-class</span>&gt;</span>org.apache.catalina.filters.CorsFilter<span class="tag">&lt;/<span class="name">filter-class</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">init-param</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">param-name</span>&gt;</span>cors.allowed.origins<span class="tag">&lt;/<span class="name">param-name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">param-value</span>&gt;</span>*<span class="tag">&lt;/<span class="name">param-value</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">init-param</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">init-param</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">param-name</span>&gt;</span>cors.allowed.methods<span class="tag">&lt;/<span class="name">param-name</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">param-value</span>&gt;</span>GET,POST,HEAD,OPTIONS,PUT<span class="tag">&lt;/<span class="name">param-value</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">init-param</span>&gt;</span>   </span><br><span class="line">    <span class="tag">&lt;/<span class="name">filter</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">filter-mapping</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">filter-name</span>&gt;</span>CorsFilter<span class="tag">&lt;/<span class="name">filter-name</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">url-pattern</span>&gt;</span>/*<span class="tag">&lt;/<span class="name">url-pattern</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">filter-mapping</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--...--&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">web-app</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>添加完成后重启Tomcat使配置生效。</p>
<h2 id="前端开源JS库"><a href="#前端开源JS库" class="headerlink" title="前端开源JS库"></a>前端开源JS库</h2><p><strong>Web的地图API分类</strong>：</p>
<ul>
<li>Charts：以D3.js，Echarts等为代表。</li>
<li>LBS：以高德/谷歌/百度地图等为代表。</li>
<li>WebGIS商业API：ESRI的ArcGIS API For JS，超图的IClient。</li>
<li>WebGIS开源API:   Leaflet，OpenLayers，Cesium，MapboxGL等。</li>
</ul>
<p><strong>应用场景</strong>：</p>
<ul>
<li><p>Charts类型在各种业务页面或后台管理页面很常见，适用业务场景是地图非页面表达的主体，且几乎没有交互，页面中同时还有其他各类主题。</p>
</li>
<li><p>LBS（基于位置的服务）广泛应用于互联网类应用，在这个时代人们的衣食住行与这些地图网站、地图APP及其背后的地理信息服务日益紧密。LBS必须要在连接互联网场景中使用，只能使用地图服务商提供的数据和服务，最多支持自定义用户标记若干兴趣点的简单操作，复杂企业级地理数据展示分析等几乎无能为力。</p>
</li>
</ul>
<p><strong>WebGIS发展历程</strong>：</p>
<p>Html5标准确立前，Flex，JS，Silverlight作为前端开发的主要技术，这个时代JS还没有取得优势，产品都以Flex为首推。WebGIS以ArcGIS的Flex API（也有JS版）和开源的OpenScale（openlayer2 是其JS版）为代表。随着时代发展，移动互联网的崛起，H5标准发布，H5技术及其主力语言JS获得一统前端的地位，很多基于H5标准的WebGIS引擎纷纷入场，WebGIS H5时代开启。</p>
<ul>
<li>2011年3月，<strong>WebGL</strong>1.0标准发布。（浏览器渲染技术（如WebGL），让浏览器可以借助系统显卡展示2D和3D地图，还能创建复杂的导航和数据视觉化效果）</li>
<li>2011年5月，<strong>Leaflet</strong>发布v0.1版本，基于H5草案，只来得及支持Canvas，与WebGL擦肩而过，以后也再没实现WebGL。</li>
<li>2012年底，H5标准发布。</li>
<li>2013年中，<strong>OpenLayer</strong>3测试版发布，与OpenLayer2不同，3是基于H5标准完全重写的，并不是迭代升级，而是一个全新的产品，只是继承了Openlayer这个已获得认可的名称与产品定位，应该说产品定位继承的相当彻底且发扬光大，只是过于保守，从而没能设想进入三维，满足于自己的二维领域。</li>
<li>2013年制定WebGL2.0标准。</li>
<li>2014年秋，<strong>Cesium</strong>发布1.0版本，开源WebGIS引擎进入三维时代。</li>
<li>2016年春，ArcGIS API for JS 4.0发布，商业WebGIS引擎进入三维时代。</li>
<li>2017年2月，WebGL2.0标准发布。</li>
<li>2019年中，<strong>MapboxGL</strong>发布1.0版本，地图可视化从功能迈向了性能，颜值等方向，更多人发现原来地图还可以这样展示，更多的客户需要更加个性化的地图更加舒服的用户体验。</li>
<li>2020年12月，MapboxGL发布2.0版本，支持三维相机参数，地形，地图最大倾角从60°到85°等，终于摆脱2.5D的产品印象。</li>
</ul>
<p><strong>WebGIS引擎各自特点与适用业务场景</strong>：</p>
<ul>
<li> <strong>LeafLet</strong>，Canvas渲染机制，仅支持二维表达，地图坐标系墨卡托投影，不支持球，特点是入手简单，缺陷是不支持webgl渲染性能有瓶颈，适用于轻量级简单地理信息主题可视化。</li>
<li> <strong>OL6</strong>，WebGL渲染机制，仅支持二维表达，不限制坐标系，不支持球，特点是二维GIS功能最丰富全面，缺陷地图样式简单，难以定制高颜值的可视化效果，不支持三维，适用于传统地理信息强GIS的二维数据Web维护和展示，面向公网地图颜值上有些上不了台面。</li>
<li> <strong>Cesium</strong>，WebGL渲染机制，二三维一体化，经纬度坐标系，支持球，明星数据格式是3DTiles，特点是唯一开源的WebGIS三维引擎，缺陷是卡，体验差，地图丑，原因应该是为了支持球，所有的平面瓦片都要进行纹理转换贴球，计算量偏大，最新的矢量切片也是变成图片再纹理转换到球上，栅格化严重一点都不精美，可以说为了球，牺牲了太多性能和地图美观度，适用于Web强三维应用场景。</li>
<li> <strong>ArcGIS API JS 4</strong>，对标Cesium，明星数据格式是I3S，也有类似Cesium的问题，但由于有ArcGIS平台的体系支持，应该功能最强大，但是如果不采购这个平台体系，纯API很鸡肋，适合采购了商业平台的用户，如政府采购再定制应用方式。</li>
<li> <strong>MapboxGL</strong>，WebGL渲染机制，二三维一体化，墨卡托坐标系，不支持球，明星数据格式是矢量切片，特点是最具美感的专题地图，缺点是没有球，最新2.0必须联网验证token，适用于互联网场景复杂地理信息表达，内网追求地图可视化效果的也适用，Mapbox很多优化都是基于互联网场景的。</li>
</ul>
<p>在WebGIS 3D领域，比较有争议性的是cesium与mapboxgl。       </p>
<p>对于Cesium的API用户来说，加载倾斜摄影，点云数据，地形数据都是直接调用引擎API就可以了，即使不懂WebGL也很快能做个三维的地图样子，当然高级开发者还会基于WebGL开发自定义高级显示效果。</p>
<p>对于Mapbox的API用户来说，2.0版本之前三维不足，主打的<strong>二维的矢量切片技术</strong>，并且切片加载机制导致倾角太大性能很差，因此引擎限制了最大倾角为60°，看起来就很像2.5D的东西。类似Cesium的三维功能只能依靠Deck.gl等库去集成，万幸的是引擎开放了自定义WebGL图层功能，高级开发者可以定制自己的三维图层，但坑爹的是没有三维相机参数需要自己源码扩展。2.0版本之后新增的地形3D展示，三维开发需要的相机参数，地图倾角限制从60°改成85°，比较有三维感觉了，效果辅助和性能优化方向考虑的Sky  API等，显示了MapboxGL开始在三维方向发力，但<strong>仍然没有在官方API层面支持倾斜摄影的3Dtiles，点云等</strong>，不熟悉WebGL的开发者使用仍然很困难。除此以外，值得警惕的地方是<strong>2.0的开源协议从商业友好的BSD-3改成了Mapbox自己的使用协议，无论是否使用Mapbox资源强制进行在线token计数</strong>，等于完全放弃了内网用户（不联网没法计数等于没法用），因此从安全和商业应用开发角度，请不要升级到2.0，保持在1.13版本进行企业定制化开发。</p>
<p>虽然mapbox更改了使用协议，但不否认它仍是家伟大的公司，在现有的技术体系下，开创性的提出数据用矢量切片技术，图标用sprite（互联网应用场景的同学很熟悉，减少网络请求的优化，合并的图标纹理减少webgl渲染的调用命令次数），字体用字体pbf切片，就是怎么极致优化怎么做，强大的技术流风格。</p>
<p><strong>后H5时代的WebGIS</strong>：</p>
<p>把时间线后移4，5年，在后H5时代的WebGIS会形成“云渲染”、“WebAssemble”、“WebGPU”新的三足鼎立。</p>
<ul>
<li>云渲染</li>
</ul>
<p>​    原理：C端使用游戏引擎做数据可视化，可视化的结果通过视频流传到客户端显示。</p>
<p>​    优点：游戏引擎比较成熟，效果好，三维大量数据，美术资源等不用传到客户端。</p>
<p>​    缺点：完全放弃日益先进强大的客户端计算资源（摩尔定律），完全依靠服务器资源，导致服务器资源投入很大，如果有高并发，起码得有分布式GPU计算引擎吧？所以不可能广泛应用，业务场景很小，只适合大屏可视化目前。</p>
<ul>
<li>WebAssemble</li>
</ul>
<p>​     原理：能让c++,rust等高性能语言写的功能以wasm形式在Web端应用，弥补JS性能的缺陷，（经过谷歌V8引擎优化，JS的性能也是直逼后台，缺陷有点牵强，而且前端计算可以使用GPGPU，WebWork等技术在gpu，在多线程非阻塞计算）当然更主要的用处是有利于原先C端图形软件如CAD，GoogleEarth搬到BS上，例如GoogleEarth的BS版已经实现了。</p>
<p>​     优点：可以用高性能语言写的算法应用到前端改进JS的算法（牵强，实际投入产出比不大对绝大部分公司），大量的后端程序员开始进入前端搞事情，前端不再是JS程序员的前端（从性能方向考虑甚至产生是否WebAssemble会取代JS的疑问）。</p>
<p>​       缺点：WebAssemble不能操作dom，因此它只是一个补充，给前端留个“后路”而已，并没有取代JS的能力也没有这样的定位。另外业务应用场景非常狭窄，只适合有成熟C端图形产品搬到BS，对一般业务产品冲击不大。从公司角度如果没有C端成熟图形产品就不值得投入，从程序员个人角度，如果是JS程序员可以直接无视，这种技术不会对你产生任何影响，如果是后端程序员，可以兴奋起来，你可以去前端玩玩了。。。</p>
<ul>
<li>WebGPU</li>
</ul>
<p>​    原理：下一代Web图形引擎，WebGL的替代者，业务场景就是现在用WebGL的地方，将来也都是WebGPU应用的场景。</p>
<p>​     优点：BS端的图形引擎与C端几乎一致（差半代），可以设想很多原先只有C端能做的酷炫效果B端也能做。（WebGL与C端差了好多代了，所以没法做出能追上C端效果的东西）</p>
<p>​     缺点：目前正式标准还没发布，那么基于WebGPU的图形，GIS引擎当然也没有了，就算有了，酷炫效果也不是GIS API这种，更多是图形学领域，大部分目前的业务API开发者会失去竞争力。</p>
<p><strong>总结</strong>：</p>
<p>如果不懂图形学原理，就算使用了WebGL的GIS引擎是做不出符合业务发展的东西来的，顶多加加地形加个建筑做做项目而已，稍微个性化的展示都做不了。从后H5时代来看，一方面可能C++,Rust等技术会更加如鱼得水，那么依靠JS的程序员和依靠JS实现可视化的公司只能抱紧WebGPU的大腿，要在图形学领域持续进行技术投入，纯调用API实现效果的时代一去不复返了，更加先进的图形引擎与更加灵活的渲染管线，再与更加个性化的业务展示要求结合与促进，会产生新的思想碰撞和化学反应，如果个人和公司跟不上，那么在下个时代，才真的是遇到”降维打击”了。</p>
<p>地理可视化（尤其3D）的未来并不属于GIS，而是属于图形学，所谓万变不离其宗。</p>
<h3 id="OpenLayers"><a href="#OpenLayers" class="headerlink" title="OpenLayers"></a>OpenLayers</h3><p>OpenLayers（<a target="_blank" rel="noopener" href="http://openlayers.org/">http://openlayers.org</a>）是一个专为 Web GIS 客户端开发提供的<strong>二维GIS</strong> JavaScript 类库包，用于实现标准格式发布的地图数据访问。由于自身较为重的原因，难于扩展，社区生态插件比较少，主要还是依赖官方的库实现绘制编辑功能。</p>
<p>OpenLayers 支持的地图来源包括  Google Maps、Yahoo、 Map、微软 Virtual Earth 等，用户还可以用简单的图片地图作为背景图，与其他的图层在  OpenLayers 中进行叠加。除此之外，OpenLayers 实现访问地理空间数据的方法都符合行业标准。OpenLayers 支持 Open GIS 协会制定的 WMS（Web Mapping Service）和 WFS（Web Feature  Service）等网络服务规范，可以通过远程服务的方式，将以 OGC 服务形式发布的地图数据加载到基于浏览器的 OpenLayers  客户端中进行显示。</p>
<p>使用开源的 GeoServer 和 OpenLayers 发布地图服务在 Web GIS 部署中比较常用。</p>
<h3 id="Leaflet"><a href="#Leaflet" class="headerlink" title="Leaflet"></a>Leaflet</h3><p>leaflet(<a target="_blank" rel="noopener" href="https://leafletjs.com/)%E6%98%AF%E4%B8%80%E4%B8%AA%E8%BD%BB%E9%87%8F%E7%9A%84**%E4%BA%8C%E7%BB%B4GIS**%E7%9A%84JS%E5%BA%93%E3%80%82%E5%AE%9E%E7%8E%B0%E7%BB%98%E5%88%B6%E7%BC%96%E8%BE%91%E5%8F%AF%E4%BB%A5%E4%BE%9D%E9%9D%A0%E7%A4%BE%E5%8C%BA%E7%9A%84%E6%8F%92%E4%BB%B6%EF%BC%8C%E4%B8%BB%E8%A6%81%E6%9C%89">https://leafletjs.com/)是一个轻量的**二维GIS**的JS库。实现绘制编辑可以依靠社区的插件，主要有</a> Leaflet.draw 、Leaflet.geoman(前身为Leaflet.pm)、Leaflet.Editable等绘制插件。</p>
<h3 id="MapboxGL"><a href="#MapboxGL" class="headerlink" title="MapboxGL"></a>MapboxGL</h3><p>MapboxGL不同于Mapbox，MapboxGL底层采用webGL实现，性能和体验显著的提升，Mapbox则是采用leaflet。MapboxGL在用户体验和性能上个人觉得都是最优的，gl版本起步较晚。社区生态插件也不是很多，但是官方也提供了相应的绘制插件。</p>
<p>官方提供了插件  mapbox-gl-draw ，总体来看，该库封装得较为成熟，最重要的是它在大数据量下的编辑一点都不卡(仅编辑点击的时候添加控制点)。</p>
<p>Mapbox地图使用矢量切片技术和地图渲染技术（Mapbox GL）实现。前端通过Mapbox GL JS进行渲染，Mapbox GL JS是一个Java Script库，使用WebGL渲染交互式矢量瓦片地图和栅格瓦片地图，渲染性能高。它能够解析各种来源的矢量数据，然后在客户端实时渲染生成带有几何图形、文字标注、图示符号3D场景地图。Mapbox GL JS不仅能够渲染大数据量的地图要素，拥有流畅的交互以及动画效果，而且还可以显示立体地图。 </p>
<p>mapbox.js 和 mapbox-gl.js有什么区别？</p>
<p>相同点：</p>
<p>1、两者都是Mapbox公司推出的免费（每月有使用次数的限制）开源的JavaScript库</p>
<p>2、都可以作为前端渲染矢量瓦片交互地图的工具（WMS、普通瓦片等地图也都支持）</p>
<p>3、它们的样式设置都是支持Mapbox Style的</p>
<p>主要的不同点：</p>
<p>1、Mapbox.js是Leaflet的一个插件，使用方式是通过结合leaflet使用。</p>
<p>2、mapbox-gl.js 则是使用WebGL技术独立渲染前端库，不需要结合其它渲染引擎（比如Leaflet、OpenLayer）来使用。</p>
<p>3、使用mapbox-gl.js的浏览器必须支持WebGL渲染，在老旧的浏览器中是不支持mapbox-gl.js的。而mapbox.js则没有此限制。</p>
<h4 id="MapboxGL基础"><a href="#MapboxGL基础" class="headerlink" title="MapboxGL基础"></a>MapboxGL基础</h4><p>MapboxGL的地图对象Map有<strong>参数</strong>，<strong>实例成员</strong>和<strong>事件</strong>。</p>
<ol>
<li><p>参数：</p>
<p><strong>container</strong>（进行地图渲染的 dom元素id）、style（地图样式）、zoom（地图初始化时的层级）、center（地图初始化时的地理中心点）等；</p>
</li>
<li><p>实例成员：</p>
<p><strong>addSource</strong>(id,source)添加数据源、<strong>addLayer</strong>(layer)添加图层、loadImage(url,callback)、addImage(id,image)等</p>
</li>
<li><p>事件：</p>
<p>比如on(type,listener)，可以为特定类型的事件添加监听器，其中type(string)添加监听器的事件类型，（包括’mousedown’ ， ‘mouseup’ ，’mousemove’、’click’、’load’），listener(Function)事件被触发时调用的函数；</p>
</li>
</ol>
<p>数据源<code>Source</code>表明地图应显示哪些数据。使用<code>“type”</code>属性指定源的类型，该属性必须是 vector, raster, raster-dem, geojson, image, video（矢量，栅格，栅格dem，geojson，图像，视频）之一。</p>
<blockquote>
<p>GeoJSON源数据必须通过<code>data</code>属性提供，其属性可以是URL或内联GeoJSON。</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;geojson-marker&quot;</span>: &#123;</span><br><span class="line">    <span class="string">&quot;type&quot;</span>: <span class="string">&quot;geojson&quot;</span>,</span><br><span class="line">    <span class="string">&quot;data&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;type&quot;</span>: <span class="string">&quot;Feature&quot;</span>,</span><br><span class="line">        <span class="string">&quot;geometry&quot;</span>: &#123;</span><br><span class="line">            <span class="string">&quot;type&quot;</span>: <span class="string">&quot;Point&quot;</span>,</span><br><span class="line">            <span class="string">&quot;coordinates&quot;</span>: [-<span class="number">77.0323</span>, <span class="number">38.9131</span>]</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="string">&quot;properties&quot;</span>: &#123;</span><br><span class="line">            <span class="string">&quot;title&quot;</span>: <span class="string">&quot;Mapbox DC&quot;</span>,</span><br><span class="line">            <span class="string">&quot;marker-symbol&quot;</span>: <span class="string">&quot;monument&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>添加一个<code>Source</code>不足以使数据显示在地图上，因为<code>source</code>不包含颜色或宽度等样式细节。图层<code>Layer</code>为<code>source</code>提供可视化表示。这样就可以以不同的方式对同一<code>source</code>进行样式设置。</p>
<blockquote>
<p><code>id</code>是唯一的图层名称。</p>
<p>图层的类型由<code>&#39;type&#39;</code>属性指定，并且必须是<code>background</code>, <code>fill</code>, <code>line</code>, <code>symbol</code>, <code>raster</code>, <code>circle</code>, <code>fill-extrusion</code>, <code>heatmap</code>, <code>hillshade</code>（背景（颜色或者图案），填充（具有可选描边边框的填充多边形），线，符号（图标或文字标签），栅格，实心圆，拉伸的（3D）多边形，热图，山体阴影）。</p>
<p>除了背景类型的图层外，每个图层都需要引用源<code>source</code>。图层将从源中获取数据。</p>
<p>图层具有两个子属性，这些子属性确定如何渲染该图层中的数据：布局<code>layout</code>和绘画<code>paint</code>属性。</p>
<p>布局属性显示在图层的<code>layout</code>对象中。它们将在渲染过程的早期应用，绘画属性将在稍后的渲染过程中应用。绘画属性显示在图层的<code>paint</code>对象中。</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;layers&quot;</span>: [</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="string">&quot;id&quot;</span>: <span class="string">&quot;water&quot;</span>,</span><br><span class="line">    <span class="string">&quot;type&quot;</span>: <span class="string">&quot;fill&quot;</span>,</span><br><span class="line">    <span class="string">&quot;source&quot;</span>: <span class="string">&quot;mapbox-streets&quot;</span>,</span><br><span class="line">    <span class="string">&quot;paint&quot;</span>: &#123;</span><br><span class="line">      <span class="string">&quot;fill-color&quot;</span>: <span class="string">&quot;#00ffff&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<p>简单demo</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;utf-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Display a map<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;initial-scale=1,maximum-scale=1,user-scalable=no&quot;</span> /&gt;</span></span><br><span class="line">    &lt;-- 引入相关的库 --&gt;</span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">link</span> <span class="attr">href</span>=<span class="string">&quot;https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.css&quot;</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">    <span class="selector-tag">body</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">margin</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">    &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">    <span class="selector-id">#map</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">top</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">bottom</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">    &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;map&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    <span class="comment">// 访问令牌accessToken</span></span></span><br><span class="line"><span class="language-javascript">    mapboxgl.<span class="property">accessToken</span> = <span class="string">&#x27;pk.eyJ1IjoieGlhb3NoaWhkIiwiYSI6ImNrNngzYnRhdzBqNm0zZnJ4eWZjdndrYzkifQ.qQjf8zANr9PsMpwq2NsRWQ&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript">    <span class="comment">// 地图对象Map</span></span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">var</span> map = <span class="keyword">new</span> mapboxgl.<span class="title class_">Map</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">container</span>: <span class="string">&#x27;map&#x27;</span>, <span class="comment">// Mapbox GL JS 进行地图渲染的 HTML 元素</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">style</span>: <span class="string">&#x27;mapbox://styles/mapbox/streets-v11&#x27;</span>, <span class="comment">// 地图的 Mapbox 配置样式</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">center</span>: [-<span class="number">74.5</span>, <span class="number">40</span>], <span class="comment">// 地图初始化时的地理中心点 [lng, lat]</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">zoom</span>: <span class="number">9</span> <span class="comment">// 地图初始化时的层级</span></span></span><br><span class="line"><span class="language-javascript">    &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>可以看出最核心的代码就是 <code>style: &#39;mapbox://styles/mapbox/streets-v11&#39;</code>，他包含了所有的地图样式。</p>
<p>将style分解，为后面离线部署提供解决方案,具体可以查看一下<a target="_blank" rel="noopener" href="https://www.mapbox.com/mapbox-gl-js/style-spec">style api</a>：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;utf-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Display a map<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;initial-scale=1,maximum-scale=1,user-scalable=no&quot;</span> /&gt;</span></span><br><span class="line">    &lt;-- 引入相关的库 --&gt;</span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">link</span> <span class="attr">href</span>=<span class="string">&quot;https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.css&quot;</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">    <span class="selector-tag">body</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">margin</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">    &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">    <span class="selector-id">#map</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">top</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">bottom</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">    &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;map&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    <span class="comment">// 访问令牌accessToken</span></span></span><br><span class="line"><span class="language-javascript">    mapboxgl.<span class="property">accessToken</span> = <span class="string">&#x27;pk.eyJ1IjoieGlhb3NoaWhkIiwiYSI6ImNrNngzYnRhdzBqNm0zZnJ4eWZjdndrYzkifQ.qQjf8zANr9PsMpwq2NsRWQ&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript">    <span class="comment">// 地图对象Map</span></span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">var</span> map = <span class="keyword">new</span> mapboxgl.<span class="title class_">Map</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">container</span>: <span class="string">&#x27;map&#x27;</span>, <span class="comment">// Mapbox GL JS 进行地图渲染的 HTML 元素</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">style</span>: &#123; </span></span><br><span class="line"><span class="language-javascript">                 <span class="string">&quot;version&quot;</span>: <span class="number">8</span>, <span class="comment">// 这个JS SDK对应版本必须为8。</span></span></span><br><span class="line"><span class="language-javascript">                 <span class="string">&quot;name&quot;</span>: <span class="string">&quot;Mapbox Streets&quot;</span>, <span class="comment">// 样式的命名</span></span></span><br><span class="line"><span class="language-javascript">                 <span class="string">&quot;sprite&quot;</span>: <span class="string">&quot;mapbox://sprites/mapbox/streets-v8&quot;</span>, <span class="comment">// 将一个地图涉及到的所有零星图标图片都包含到一张大图中去</span></span></span><br><span class="line"><span class="language-javascript">                 <span class="string">&quot;glyphs&quot;</span>: <span class="string">&quot;mapbox://fonts/mapbox/&#123;fontstack&#125;/&#123;range&#125;.pbf&quot;</span>, <span class="comment">// .pbf格式的字体样式，例如微软雅黑等字体库</span></span></span><br><span class="line"><span class="language-javascript">                 <span class="string">&quot;sources&quot;</span>: &#123; <span class="comment">// 图层的资源文件，可以支持矢量切片、栅格、dem栅格、图片、geojson、视频等格式。</span></span></span><br><span class="line"><span class="language-javascript">                     <span class="string">&quot;mapbox-streets&quot;</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">                         <span class="string">&quot;type&quot;</span>: <span class="string">&quot;vector&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                         <span class="string">&quot;url&quot;</span>: <span class="string">&quot;mapbox://mapbox.mapbox-streets-v6&quot;</span></span></span><br><span class="line"><span class="language-javascript">                     &#125;</span></span><br><span class="line"><span class="language-javascript">                 &#125;,</span></span><br><span class="line"><span class="language-javascript">                 <span class="string">&quot;layers&quot;</span>: [ <span class="comment">// 对每个图层样式的描述，这里就是对地图样式渲染的关键，可以做很多精美的设计。</span></span></span><br><span class="line"><span class="language-javascript">                     &#123;</span></span><br><span class="line"><span class="language-javascript">                         <span class="string">&quot;id&quot;</span>: <span class="string">&quot;water&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                         <span class="string">&quot;source&quot;</span>: <span class="string">&quot;mapbox-streets&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                         <span class="string">&quot;source-layer&quot;</span>: <span class="string">&quot;water&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                         <span class="string">&quot;type&quot;</span>: <span class="string">&quot;fill&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                         <span class="string">&quot;paint&quot;</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">                             <span class="string">&quot;fill-color&quot;</span>: <span class="string">&quot;#00ffff&quot;</span></span></span><br><span class="line"><span class="language-javascript">                         &#125;</span></span><br><span class="line"><span class="language-javascript">                     &#125;</span></span><br><span class="line"><span class="language-javascript">                 ]</span></span><br><span class="line"><span class="language-javascript">             &#125;, <span class="comment">// 地图的 Mapbox 配置样式</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">center</span>: [-<span class="number">74.5</span>, <span class="number">40</span>], <span class="comment">// 地图初始化时的地理中心点 [lng, lat]</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">zoom</span>: <span class="number">9</span> <span class="comment">// 地图初始化时的层级</span></span></span><br><span class="line"><span class="language-javascript">    &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="接入WMS服务"><a href="#接入WMS服务" class="headerlink" title="接入WMS服务"></a>接入WMS服务</h4><p>官方教程：<a target="_blank" rel="noopener" href="https://docs.mapbox.com/mapbox-gl-js/example/wms/">https://docs.mapbox.com/mapbox-gl-js/example/wms/</a></p>
<p>参考：<a target="_blank" rel="noopener" href="https://blog.csdn.net/hequhecong10857/article/details/113881004">https://blog.csdn.net/hequhecong10857/article/details/113881004</a></p>
<ol>
<li>确保成功发布WMS服务并且配置好跨域。</li>
<li>在点击Openlayers预览图层时，打开调试工具，点击NetWork可获取tiles的<code>url</code>，需要将bbox参数用<code>&#123;bbox-epsg-3857&#125;</code>替换，之后修改坐标系为<code>&amp;SRS=EPSG:3857</code>（Mapbox GL支持的是<code>EPSG:3857</code>（Web墨卡托）坐标）。加载的时候，Mapbox GL会自动替换成对应的参数，这样地图就可以加载了。</li>
</ol>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210808195751.png" alt="image-20210808195750909" style="zoom:80%;" />

<ol start="3">
<li>在点击Openlayers预览图层时，打开调试工具，点击查询图层要素，NetWork中会出现一个请求<code>url</code>，而<code>axios</code>请求的<code>url</code>只需将<code>INFO_FORMAT</code>参数由<code>text/html</code>替换成<code>application/json</code>即可，获取到<code>json</code>数据后，可根据实际进行下一步操作。</li>
</ol>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210808202041.png" alt="image-20210808201040795" style="zoom:80%;" />

<ol start="4">
<li>BBOX是以SRS单位表示的边界框边角 (左下角，右上角)，但是点击返回的是点击点的坐标。需要进行换算，需要注意的是点击返回的坐标是经纬度，还需要转换成墨卡托坐标，之后请求的SRS也需要变成<code>EPSG:3857</code>。</li>
</ol>
<p><strong>代码</strong></p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;utf-8&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">title</span>&gt;</span></span><br><span class="line">            Add a WMS source and query</span><br><span class="line">        <span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">meta</span> <span class="attr">content</span>=<span class="string">&quot;initial-scale=1,maximum-scale=1,user-scalable=no&quot;</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span>/&gt;</span></span><br><span class="line">        &lt;-- 引入相关的库 --&gt;</span><br><span class="line">        <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.js&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">link</span> <span class="attr">href</span>=<span class="string">&quot;https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.css&quot;</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span>/&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--Axios网络请求库 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.js&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--地理空间分析库 https://turfjs.fenxianglu.cn/ --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://unpkg.com/@turf/turf@6.3.0/turf.min.js&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">            <span class="selector-tag">body</span> &#123;</span></span><br><span class="line"><span class="language-css">                    <span class="attribute">margin</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">                    <span class="attribute">padding</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">                &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">                <span class="selector-id">#map</span> &#123;</span></span><br><span class="line"><span class="language-css">                    <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="language-css">                    <span class="attribute">top</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">                    <span class="attribute">bottom</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">                    <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">                &#125;</span></span><br><span class="line"><span class="language-css">        </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;map&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// 访问令牌accessToken</span></span></span><br><span class="line"><span class="language-javascript">                mapboxgl.<span class="property">accessToken</span> = <span class="string">&#x27;pk.eyJ1IjoieGlhb3NoaWhkIiwiYSI6ImNrNngzYnRhdzBqNm0zZnJ4eWZjdndrYzkifQ.qQjf8zANr9PsMpwq2NsRWQ&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript">                <span class="comment">// 地图对象Map</span></span></span><br><span class="line"><span class="language-javascript">                <span class="keyword">var</span> map = <span class="keyword">new</span> mapboxgl.<span class="title class_">Map</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">container</span>: <span class="string">&#x27;map&#x27;</span>, <span class="comment">// Mapbox GL JS 进行地图渲染的 HTML 元素</span></span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">style</span>: <span class="string">&#x27;mapbox://styles/mapbox/streets-v11&#x27;</span>, <span class="comment">// 地图的 Mapbox 配置样式</span></span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">zoom</span>: <span class="number">4</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">center</span>: [<span class="number">112</span>, <span class="number">28</span>]</span></span><br><span class="line"><span class="language-javascript">                &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">                <span class="comment">// 地图加载的时候调用WMS服务</span></span></span><br><span class="line"><span class="language-javascript">                map.<span class="title function_">on</span>(<span class="string">&#x27;load&#x27;</span>, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">                    map.<span class="title function_">addSource</span>(<span class="string">&#x27;wms-source&#x27;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">                        <span class="string">&#x27;type&#x27;</span>: <span class="string">&#x27;raster&#x27;</span>,  <span class="comment">// 栅格数据</span></span></span><br><span class="line"><span class="language-javascript">                        <span class="string">&#x27;tiles&#x27;</span>: [</span></span><br><span class="line"><span class="language-javascript">                            <span class="string">&#x27;http://localhost:8088/geoserver/china/wms?SERVICE=WMS&amp;VERSION=1.1.1&amp;REQUEST=GetMap&amp;FORMAT=image%2Fpng&amp;TRANSPARENT=true&amp;STYLES&amp;LAYERS=china%3Achina_2014gdp&amp;exceptions=application%2Fvnd.ogc.se_inimage&amp;WIDTH=769&amp;HEIGHT=442&amp;BBOX=&#123;bbox-epsg-3857&#125;&amp;SRS=EPSG:3857&#x27;</span></span></span><br><span class="line"><span class="language-javascript">                        ],</span></span><br><span class="line"><span class="language-javascript">                        <span class="string">&#x27;tileSize&#x27;</span>: <span class="number">256</span></span></span><br><span class="line"><span class="language-javascript">                    &#125;);</span></span><br><span class="line"><span class="language-javascript">                    map.<span class="title function_">addLayer</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">                        <span class="string">&#x27;id&#x27;</span>: <span class="string">&#x27;wms-layer&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">                        <span class="string">&#x27;type&#x27;</span>: <span class="string">&#x27;raster&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">                        <span class="string">&#x27;source&#x27;</span>: <span class="string">&#x27;wms-source&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">                        <span class="string">&#x27;paint&#x27;</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">                            <span class="string">&#x27;raster-opacity&#x27;</span>: <span class="number">0.5</span>  <span class="comment">// 设置透明度</span></span></span><br><span class="line"><span class="language-javascript">                        &#125;</span></span><br><span class="line"><span class="language-javascript">                    &#125;,</span></span><br><span class="line"><span class="language-javascript">                                 <span class="string">&#x27;aeroway-line&#x27;</span></span></span><br><span class="line"><span class="language-javascript">                                );</span></span><br><span class="line"><span class="language-javascript">                &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">                <span class="comment">// 地图点击的时候进行属性查询</span></span></span><br><span class="line"><span class="language-javascript">                map.<span class="title function_">on</span>(<span class="string">&quot;click&quot;</span>, <span class="keyword">function</span> (<span class="params">e</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="keyword">const</span> &#123;</span></span><br><span class="line"><span class="language-javascript">                        lng,</span></span><br><span class="line"><span class="language-javascript">                        lat</span></span><br><span class="line"><span class="language-javascript">                    &#125; = e.<span class="property">lngLat</span>; <span class="comment">// 点击返回的是点击位置的经纬度</span></span></span><br><span class="line"><span class="language-javascript">                    <span class="keyword">const</span> radius = <span class="title class_">Math</span>.<span class="title function_">pow</span>(<span class="number">2</span>, <span class="number">22</span> - map.<span class="title function_">getZoom</span>());</span></span><br><span class="line"><span class="language-javascript">                    <span class="comment">// 以下为墨卡托坐标下的换算过程</span></span></span><br><span class="line"><span class="language-javascript">                    <span class="keyword">const</span> pointM = turf.<span class="title function_">toMercator</span>(turf.<span class="title function_">point</span>([lng, lat]));  <span class="comment">// 转换成EPSG:3857坐标系(墨卡托)</span></span></span><br><span class="line"><span class="language-javascript">                    <span class="keyword">const</span> pointC = pointM.<span class="property">geometry</span>.<span class="property">coordinates</span>;</span></span><br><span class="line"><span class="language-javascript">                    <span class="keyword">const</span> bbox = [pointC[<span class="number">0</span>] - radius, pointC[<span class="number">1</span>] - radius, pointC[<span class="number">0</span>] + radius, pointC[<span class="number">1</span>] + radius];</span></span><br><span class="line"><span class="language-javascript">                    <span class="keyword">const</span> url =</span></span><br><span class="line"><span class="language-javascript">                          <span class="string">&#x27;http://localhost:8088/geoserver/china/wms?SERVICE=WMS&amp;VERSION=1.1.1&amp;REQUEST=GetFeatureInfo&amp;FORMAT=image%2Fpng&amp;TRANSPARENT=true&amp;QUERY_LAYERS=china%3Achina_2014gdp&amp;STYLES&amp;LAYERS=china%3Achina_2014gdp&amp;exceptions=application%2Fvnd.ogc.se_inimage&amp;INFO_FORMAT=application%2Fjson&amp;FEATURE_COUNT=50&amp;X=50&amp;Y=50&amp;SRS=EPSG:3857&amp;WIDTH=101&amp;HEIGHT=101&amp;BBOX=&#x27;</span> +</span></span><br><span class="line"><span class="language-javascript">                          bbox.<span class="title function_">join</span>();</span></span><br><span class="line"><span class="language-javascript">                    axios.<span class="title function_">get</span>(url)  <span class="comment">// Axios进行网络请求</span></span></span><br><span class="line"><span class="language-javascript">                        .<span class="title function_">then</span>(<span class="keyword">function</span> (<span class="params">res</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">                        <span class="variable language_">console</span>.<span class="title function_">log</span>(res);</span></span><br><span class="line"><span class="language-javascript">                        <span class="title function_">alert</span>(res.<span class="property">data</span>.<span class="property">features</span>[<span class="number">0</span>].<span class="property">properties</span>.<span class="property">name</span>);</span></span><br><span class="line"><span class="language-javascript">                    &#125;)</span></span><br><span class="line"><span class="language-javascript">                &#125;);</span></span><br><span class="line"><span class="language-javascript">        </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>实现效果</strong></p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210808211120.png" alt="image-20210808211120574" style="zoom:80%;" />

<h4 id="接入矢量瓦片服务"><a href="#接入矢量瓦片服务" class="headerlink" title="接入矢量瓦片服务"></a>接入矢量瓦片服务</h4><p>参考这两篇：</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_34870529/article/details/92768540">https://blog.csdn.net/qq_34870529/article/details/92768540</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/hequhecong10857/article/details/113895245?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.control&spm=1001.2101.3001.4242">Mapbox GL 加载GeoServer发布的矢量切片</a></p>
<p>Mapbox GL只支持坐标为EPSG:3857的矢量切片，而GeoServer（version 2.13.3）默认没有该坐标系的Gridsets，需要自己手动创建。</p>
<p>创建名为EPSG:3857的Gridsets（缩放层级可自行控制，我在此处共设置了22层）：</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210809153919.png" alt="image-20210809153919417" style="zoom:80%;" />

<p>之后添加新的图层、添加新的数据存储。</p>
<p>之后添加新的图层并发布图层：</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210809154405.png" alt="image-20210809154405831" style="zoom:80%;" />

<p>切换到Tile Caching（添加刚才定义好的Gridsets 3857）：</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210809154328.png" alt="image-20210809154328641" style="zoom:80%;" />

<p>在Tile Layers页面可以看到发布的服务：</p>
<img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20210809161938.png" alt="image-20210809161938035" style="zoom:80%;" />

<p>3857我预览总是出不来数据。</p>
<p>4326和900913都可以。</p>
<p>在矢量切图教程中获取到了服务的URL。</p>
<figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://localhost:8088/geoserver/gwc/service/tms/1.0.0/china%3Achina_2014gdp@EPSG%3A900913@pbf</span><br></pre></td></tr></table></figure>

<p>拼接服务地址供mapbox调用：</p>
<figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://localhost:8088/geoserver/gwc/service/tms/1.0.0/china%3Achina_2014gdp@EPSG%3A900913@pbf/&#123;z&#125;/&#123;x&#125;/&#123;y&#125;.pbf</span><br></pre></td></tr></table></figure>

<p>4326Mapbox调用后不显示，但是900913和3857都成功显示。这也证明3857其实没必要建立。</p>
<p>代码：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;utf-8&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">title</span>&gt;</span></span><br><span class="line">            Display a map</span><br><span class="line">        <span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">meta</span> <span class="attr">content</span>=<span class="string">&quot;initial-scale=1,maximum-scale=1,user-scalable=no&quot;</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span>/&gt;</span></span><br><span class="line">        &lt;-- 引入相关的库 --&gt;</span><br><span class="line">        <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.js&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">link</span> <span class="attr">href</span>=<span class="string">&quot;https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.css&quot;</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">            <span class="selector-tag">body</span> &#123;</span></span><br><span class="line"><span class="language-css">                    <span class="attribute">margin</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">                    <span class="attribute">padding</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">                &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">                <span class="selector-id">#map</span> &#123;</span></span><br><span class="line"><span class="language-css">                    <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="language-css">                    <span class="attribute">top</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">                    <span class="attribute">bottom</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">                    <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">                &#125;</span></span><br><span class="line"><span class="language-css">        </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;map&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// 访问令牌accessToken</span></span></span><br><span class="line"><span class="language-javascript">                mapboxgl.<span class="property">accessToken</span> = <span class="string">&#x27;pk.eyJ1IjoieGlhb3NoaWhkIiwiYSI6ImNrNngzYnRhdzBqNm0zZnJ4eWZjdndrYzkifQ.qQjf8zANr9PsMpwq2NsRWQ&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript">                <span class="comment">// 地图对象Map</span></span></span><br><span class="line"><span class="language-javascript">                <span class="keyword">var</span> map = <span class="keyword">new</span> mapboxgl.<span class="title class_">Map</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">container</span>: <span class="string">&#x27;map&#x27;</span>, <span class="comment">// Mapbox GL JS 进行地图渲染的 HTML 元素</span></span></span><br><span class="line"><span class="language-javascript">                    <span class="comment">// style: &#x27;mapbox://styles/mapbox/light-v10&#x27;, // 地图的 Mapbox 配置样式</span></span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">style</span>: <span class="string">&#x27;mapbox://styles/mapbox/satellite-v9&#x27;</span>, <span class="comment">//卫星图</span></span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">zoom</span>: <span class="number">4</span>, <span class="comment">// 地图初始化时的层级</span></span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">center</span>: [<span class="number">112</span>, <span class="number">28</span>] <span class="comment">// 地图初始化时的地理中心点 [lng, lat]</span></span></span><br><span class="line"><span class="language-javascript">                &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">                map.<span class="title function_">on</span>(<span class="string">&#x27;load&#x27;</span>, <span class="keyword">function</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">                    map.<span class="title function_">addSource</span>(<span class="string">&#x27;tms-source&#x27;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">                        <span class="string">&#x27;type&#x27;</span>: <span class="string">&#x27;vector&#x27;</span>,  <span class="comment">// 矢量数据</span></span></span><br><span class="line"><span class="language-javascript">                        <span class="string">&quot;scheme&quot;</span>:<span class="string">&quot;tms&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                        <span class="string">&#x27;tiles&#x27;</span>: [</span></span><br><span class="line"><span class="language-javascript">                            <span class="comment">// &#x27;http://localhost:8088/geoserver/gwc/service/tms/1.0.0/china%3Achina_2014gdp@EPSG%3A900913@pbf/&#123;z&#125;/&#123;x&#125;/&#123;y&#125;.pbf&#x27;</span></span></span><br><span class="line"><span class="language-javascript">                            <span class="string">&#x27;http://localhost:8088/geoserver/gwc/service/tms/1.0.0/northLaker%3Alakemaxextent_north@EPSG%3A3857@pbf/&#123;z&#125;/&#123;x&#125;/&#123;y&#125;.pbf&#x27;</span></span></span><br><span class="line"><span class="language-javascript">                        ],</span></span><br><span class="line"><span class="language-javascript">                    &#125;);</span></span><br><span class="line"><span class="language-javascript">                    map.<span class="title function_">addLayer</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">                        <span class="string">&#x27;id&#x27;</span>: <span class="string">&#x27;tms-layer&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">                        <span class="string">&#x27;type&#x27;</span>: <span class="string">&#x27;fill&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">                        <span class="string">&#x27;source&#x27;</span>: <span class="string">&#x27;tms-source&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">                        <span class="comment">// &quot;source-layer&quot;: &quot;china_2014gdp&quot;,  // 图层名称</span></span></span><br><span class="line"><span class="language-javascript">                        <span class="string">&quot;source-layer&quot;</span>: <span class="string">&quot;lakemaxextent_north&quot;</span>,  <span class="comment">// 图层名称</span></span></span><br><span class="line"><span class="language-javascript">                        <span class="string">&#x27;paint&#x27;</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">                            <span class="string">&quot;fill-color&quot;</span>:<span class="string">&quot;#ff0000&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                            <span class="string">&quot;fill-opacity&quot;</span>:<span class="number">0.3</span></span></span><br><span class="line"><span class="language-javascript">                        &#125;</span></span><br><span class="line"><span class="language-javascript">                    &#125;);</span></span><br><span class="line"><span class="language-javascript">                &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">                <span class="comment">// 添加mapbox自带菜单</span></span></span><br><span class="line"><span class="language-javascript">                map.<span class="title function_">addControl</span>(<span class="keyword">new</span> mapboxgl.<span class="title class_">NavigationControl</span>());</span></span><br><span class="line"><span class="language-javascript">        </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="Mapbox样式"><a href="#Mapbox样式" class="headerlink" title="Mapbox样式"></a>Mapbox样式</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> mapboxStyle = [</span><br><span class="line">    <span class="string">&#x27;http://61.161.150.90:5081/api/v1/styles/aolutong/Bkl7eaQNyU&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;http://61.161.150.90:5081/api/v1/styles/aolutong/HJeN6h7VyL&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;http://61.161.150.90:5081/api/v1/styles/aolutong/ByetWaXVJL&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;mapbox://styles/mapbox/satellite-v9&#x27;</span>,</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<p>自定义样式其实就是返回配置的json文件，在json文件里面调用矢量瓦片的接口请求数据源：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;updatedAt&quot;</span><span class="punctuation">:</span> <span class="string">&quot;2020-12-23T07:04:03.832Z&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;owner&quot;</span><span class="punctuation">:</span> <span class="string">&quot;aolutong&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;format&quot;</span><span class="punctuation">:</span> <span class="string">&quot;pbf&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;description&quot;</span><span class="punctuation">:</span> <span class="string">&quot;ln_peak&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;ln_peak&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;createdAt&quot;</span><span class="punctuation">:</span> <span class="string">&quot;2020-12-23T06:56:35.787Z&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;vector_layers&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;fieldalias&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;dists_code&quot;</span><span class="punctuation">:</span> <span class="string">&quot;区划代码&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;town_code&quot;</span><span class="punctuation">:</span> <span class="string">&quot;乡镇行政区代码&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;town_name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;所属乡镇&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;city_code&quot;</span><span class="punctuation">:</span> <span class="string">&quot;市级行政代码&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;city_name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;所属市级&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;province_code&quot;</span><span class="punctuation">:</span> <span class="string">&quot;省份行政代码&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;province_name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;所属省份&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;类型&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;名称&quot;</span></span><br><span class="line">      <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;fields&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;dists_code&quot;</span><span class="punctuation">:</span> <span class="string">&quot;String&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;town_code&quot;</span><span class="punctuation">:</span> <span class="string">&quot;String&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;town_name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;String&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;city_code&quot;</span><span class="punctuation">:</span> <span class="string">&quot;String&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;city_name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;String&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;province_code&quot;</span><span class="punctuation">:</span> <span class="string">&quot;String&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;province_name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;String&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;String&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;String&quot;</span></span><br><span class="line">      <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;description&quot;</span><span class="punctuation">:</span> <span class="string">&quot;山峰&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;id&quot;</span><span class="punctuation">:</span> <span class="string">&quot;ln_peak&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;_id&quot;</span><span class="punctuation">:</span> <span class="keyword">null</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;center&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="number">125.530673</span><span class="punctuation">,</span></span><br><span class="line">    <span class="number">40.784181</span><span class="punctuation">,</span></span><br><span class="line">    <span class="number">18</span></span><br><span class="line">  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;bounds&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="number">73.49735</span><span class="punctuation">,</span></span><br><span class="line">    <span class="number">6.318649</span><span class="punctuation">,</span></span><br><span class="line">    <span class="number">134.773613</span><span class="punctuation">,</span></span><br><span class="line">    <span class="number">53.561648</span></span><br><span class="line">  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;maxzoom&quot;</span><span class="punctuation">:</span> <span class="number">18</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;minzoom&quot;</span><span class="punctuation">:</span> <span class="number">10</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;data&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;grids&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;tiles&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="string">&quot;http://124.70.71.54:8080/api/v1/tilesets/aolutong/ln_peak/&#123;z&#125;/&#123;x&#125;/&#123;y&#125;.pbf&quot;</span></span><br><span class="line">  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;scheme&quot;</span><span class="punctuation">:</span> <span class="string">&quot;xyz&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;version&quot;</span><span class="punctuation">:</span> <span class="string">&quot;2&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;tilejson&quot;</span><span class="punctuation">:</span> <span class="string">&quot;2.1.0&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;tags&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;scope&quot;</span><span class="punctuation">:</span> <span class="string">&quot;public&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;tileset_id&quot;</span><span class="punctuation">:</span> <span class="string">&quot;ln_peak&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;utf-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Add Markers<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;initial-scale=1,maximum-scale=1,user-scalable=no&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">link</span> <span class="attr">href</span>=<span class="string">&quot;https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.css&quot;</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">        <span class="selector-tag">body</span> &#123;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">margin</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">padding</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">        <span class="selector-id">#map</span> &#123;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">top</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">bottom</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">        &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">        <span class="selector-id">#menu</span> &#123;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">background</span>: <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">padding</span>: <span class="number">10px</span>;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">font-family</span>: <span class="string">&#x27;Open Sans&#x27;</span>, sans-serif;</span></span><br><span class="line"><span class="language-css">        &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">        <span class="selector-id">#menu2</span> &#123;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">background</span>: <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">padding</span>: <span class="number">10px</span>;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">font-family</span>: <span class="string">&#x27;Open Sans&#x27;</span>, sans-serif;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">right</span>: <span class="number">0px</span>;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">bottom</span>: <span class="number">0px</span>;</span></span><br><span class="line"><span class="language-css">        &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;map&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;menu&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">onclick</span>=<span class="string">&quot;changeSize(true);&quot;</span> <span class="attr">style</span>=<span class="string">&quot;width:40px;height:40px&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;icons/Zoomin.png&quot;</span> <span class="attr">width</span>=<span class="string">&quot;25&quot;</span> <span class="attr">height</span>=<span class="string">&quot;25&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;放大&quot;</span> /&gt;</span><span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">onclick</span>=<span class="string">&quot;changeSize(false);&quot;</span> <span class="attr">style</span>=<span class="string">&quot;width:40px;height:40px&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;icons/Zoomout.png&quot;</span> <span class="attr">width</span>=<span class="string">&quot;25&quot;</span> <span class="attr">height</span>=<span class="string">&quot;25&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;缩小&quot;</span> /&gt;</span><span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;menu2&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">name</span>=<span class="string">&quot;style&quot;</span> <span class="attr">type</span>=<span class="string">&quot;radio&quot;</span> <span class="attr">checked</span>=<span class="string">&quot;true&quot;</span> <span class="attr">onclick</span>=<span class="string">&quot;changeStyle(0);&quot;</span> <span class="attr">style</span>=<span class="string">&quot;width:20px;height:20px&quot;</span> <span class="attr">value</span>=<span class="string">&quot;阳光白&quot;</span>&gt;</span>阳光白</span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">name</span>=<span class="string">&quot;style&quot;</span> <span class="attr">type</span>=<span class="string">&quot;radio&quot;</span> <span class="attr">onclick</span>=<span class="string">&quot;changeStyle(1);&quot;</span> <span class="attr">style</span>=<span class="string">&quot;width:20px;height:20px&quot;</span> <span class="attr">value</span>=<span class="string">&quot;暗夜蓝&quot;</span>&gt;</span>暗夜蓝</span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">name</span>=<span class="string">&quot;style&quot;</span> <span class="attr">type</span>=<span class="string">&quot;radio&quot;</span> <span class="attr">onclick</span>=<span class="string">&quot;changeStyle(2);&quot;</span> <span class="attr">style</span>=<span class="string">&quot;width:20px;height:20px&quot;</span> <span class="attr">value</span>=<span class="string">&quot;清淡蓝&quot;</span>&gt;</span>清淡蓝</span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">name</span>=<span class="string">&quot;style&quot;</span> <span class="attr">type</span>=<span class="string">&quot;radio&quot;</span> <span class="attr">onclick</span>=<span class="string">&quot;changeStyle(3);&quot;</span> <span class="attr">style</span>=<span class="string">&quot;width:20px;height:20px&quot;</span> <span class="attr">value</span>=<span class="string">&quot;遥感&quot;</span>&gt;</span>遥感</span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    mapboxgl.<span class="property">accessToken</span> = <span class="string">&#x27;pk.eyJ1IjoieGlhb3NoaWhkIiwiYSI6ImNrNngzYnRhdzBqNm0zZnJ4eWZjdndrYzkifQ.qQjf8zANr9PsMpwq2NsRWQ&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">let</span> mapboxStyle = [</span></span><br><span class="line"><span class="language-javascript">        <span class="string">&#x27;http://61.161.150.90:5081/api/v1/styles/aolutong/Bkl7eaQNyU&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="string">&#x27;http://61.161.150.90:5081/api/v1/styles/aolutong/HJeN6h7VyL&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="string">&#x27;http://61.161.150.90:5081/api/v1/styles/aolutong/ByetWaXVJL&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="string">&#x27;mapbox://styles/mapbox/satellite-v9&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">    ]</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">var</span> map = <span class="keyword">new</span> mapboxgl.<span class="title class_">Map</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">container</span>: <span class="string">&#x27;map&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">style</span>: mapboxStyle[<span class="number">0</span>],</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">center</span>: [<span class="number">123.38</span>, <span class="number">41.8</span>],</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">zoom</span>: <span class="number">5</span></span></span><br><span class="line"><span class="language-javascript">    &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">function</span> <span class="title function_">changeSize</span>(<span class="params">bool</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">if</span> (bool) &#123;</span></span><br><span class="line"><span class="language-javascript">            map.<span class="title function_">setZoom</span>(map.<span class="title function_">getZoom</span>() + <span class="number">1</span>);</span></span><br><span class="line"><span class="language-javascript">        &#125; <span class="keyword">else</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            map.<span class="title function_">setZoom</span>(map.<span class="title function_">getZoom</span>() - <span class="number">1</span>);</span></span><br><span class="line"><span class="language-javascript">        &#125;</span></span><br><span class="line"><span class="language-javascript">    &#125;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">function</span> <span class="title function_">changeStyle</span>(<span class="params">num</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        map.<span class="title function_">setStyle</span>(mapboxStyle[num]);</span></span><br><span class="line"><span class="language-javascript">    &#125;</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/ATtuing/p/9085312.html">开源方案搭建可离线的精美矢量切片地图服务-1.开篇（附成果演示地址）</a></p>
<p>Mapbox官方提供的在线样式编辑器：</p>
<p><a target="_blank" rel="noopener" href="https://studio.mapbox.com/styles/">https://studio.mapbox.com/styles/</a></p>
<h2 id="空间分析库"><a href="#空间分析库" class="headerlink" title="空间分析库"></a>空间分析库</h2><p>Turf.js 是一个开源的空间分析库，由 Mapbox 提供。<a target="_blank" rel="noopener" href="https://github.com/Turfjs/turf">源码地址</a>，在其(官网)[]中都有 Mapbox 作为底图的示例。</p>
<p>并且在 Mapbox 官网也推荐使用 Turf.js 作为空间分析库。</p>
<p>缓冲分析这些功能可以用的postgis自带的空间分析函数。</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://xiaoshihd.gitee.io/xiaoshihd/2022/04/22/Android%E5%B5%8C%E5%85%A5Vue%E5%AE%9E%E7%8E%B0H5%E5%BA%94%E7%94%A8/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/xiaoshihd/images/xiaoshi.png">
      <meta itemprop="name" content="XiaoShi">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="小师的Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/xiaoshihd/2022/04/22/Android%E5%B5%8C%E5%85%A5Vue%E5%AE%9E%E7%8E%B0H5%E5%BA%94%E7%94%A8/" class="post-title-link" itemprop="url">Android嵌入Vue实现H5应用</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2022-04-22 17:20:30" itemprop="dateCreated datePublished" datetime="2022-04-22T17:20:30+08:00">2022-04-22</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2022-04-23 11:03:17" itemprop="dateModified" datetime="2022-04-23T11:03:17+08:00">2022-04-23</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/xiaoshihd/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="Android嵌入Vue实现H5应用"><a href="#Android嵌入Vue实现H5应用" class="headerlink" title="Android嵌入Vue实现H5应用"></a>Android嵌入Vue实现H5应用</h2><p>现在很多的App里都内置了Web网页（Hybrid App），比如说很多电商平台，淘宝、京东、聚划算等等。</p>
<p>他们的页面是由Android的WebView实现的，其中涉及到Android客户端与Web网页的交互。</p>
<p>Android WebView组件可以实现App中内置网页的功能。</p>
<p><code>WebView</code>是一个基于<code>webkit</code>引擎、展现<code>web</code>页面的控件。</p>
<blockquote>
<p>Android的Webview在低版本和高版本采用了不同的webkit版本内核，4.4后直接使用了Chrome。</p>
</blockquote>
<p>作用为：</p>
<ul>
<li>显示和渲染Web页面</li>
<li>直接使用html文件（网络上或本地assets中）作布局</li>
<li>可和JavaScript交互调用</li>
</ul>
<p>==参考WebView教程==：<a target="_blank" rel="noopener" href="https://www.jianshu.com/p/3c94ae673e2a">https://www.jianshu.com/p/3c94ae673e2a</a></p>
<p>AndroidManifest.xml<code>添加访问网络权限</code>：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.INTERNET&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<p>WebViews只能加载HTTPS的站点，无法加载HTTP站点。当加载HTTP站点时，会报错<code>net :: ERR_CLEARTEXT_NOT_PERMITTED</code>。</p>
<p>在AndroidManifest.xml的<code>application</code>标签下配置：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">application</span></span></span><br><span class="line"><span class="tag">    <span class="attr">....</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:usesCleartextTraffic</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">....</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><code>activity_main.xml</code>添加WebView组件：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">WebView</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:id</span>=<span class="string">&quot;@+id/webview&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_height</span>=<span class="string">&quot;match_parent&quot;</span> /&gt;</span></span><br></pre></td></tr></table></figure>

<p><code>MainActivity</code>找到该组件：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="type">WebView</span> <span class="variable">webView</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">onCreate</span><span class="params">(Bundle savedInstanceState)</span> &#123;</span><br><span class="line">    <span class="built_in">super</span>.onCreate(savedInstanceState);</span><br><span class="line">    setContentView(R.layout.activity_main);</span><br><span class="line"></span><br><span class="line">    webView = (WebView) findViewById(R.id.webview);</span><br><span class="line"></span><br><span class="line">    webView.loadUrl(<span class="string">&quot;https://xiaoshiapp.city/h5/index.html&quot;</span>); <span class="comment">// 加载远程网页</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>Webview常用的工具类：</p>
<ul>
<li>WebSettings类：对WebView进行配置和管理</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 声明WebSettings子类</span></span><br><span class="line"><span class="type">WebSettings</span> <span class="variable">webSettings</span> <span class="operator">=</span> webView.getSettings();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 如果访问的页面中要与Javascript交互，则webview必须设置支持Javascript</span></span><br><span class="line">webSettings.setJavaScriptEnabled(<span class="literal">true</span>);  </span><br><span class="line"><span class="comment">// 若加载的 html 里有JS 在执行动画等操作，会造成资源浪费（CPU、电量）</span></span><br><span class="line"><span class="comment">// 在 onStop 和 onResume 里分别把 setJavaScriptEnabled() 给设置成 false 和 true 即可</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//支持插件</span></span><br><span class="line">webSettings.setPluginsEnabled(<span class="literal">true</span>); </span><br><span class="line"></span><br><span class="line"><span class="comment">//设置自适应屏幕，两者结合使用</span></span><br><span class="line">webSettings.setUseWideViewPort(<span class="literal">true</span>); <span class="comment">// 将图片调整到适合webview的大小 </span></span><br><span class="line">webSettings.setLoadWithOverviewMode(<span class="literal">true</span>); <span class="comment">// 缩放至屏幕的大小</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//缩放操作</span></span><br><span class="line">webSettings.setSupportZoom(<span class="literal">true</span>); <span class="comment">// 支持缩放，默认为true。是下面操作的前提，结合使用</span></span><br><span class="line">webSettings.setBuiltInZoomControls(<span class="literal">true</span>); <span class="comment">// 设置内置的缩放控件。若为false，则该WebView不可缩放</span></span><br><span class="line">webSettings.setDisplayZoomControls(<span class="literal">false</span>); <span class="comment">// 隐藏原生的缩放控件</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 缓存操作</span></span><br><span class="line">webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); </span><br><span class="line"><span class="comment">//缓存模式如下：</span></span><br><span class="line"><span class="comment">//LOAD_CACHE_ONLY: 不使用网络，只读取本地缓存数据</span></span><br><span class="line"><span class="comment">//LOAD_DEFAULT: （默认）根据cache-control决定是否从网络上取数据。</span></span><br><span class="line"><span class="comment">//LOAD_NO_CACHE: 不使用缓存，只从网络获取数据.</span></span><br><span class="line"><span class="comment">//LOAD_CACHE_ELSE_NETWORK，只要本地有，无论是否过期，或者no-cache，都使用缓存中的数据。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//其他细节操作</span></span><br><span class="line">webSettings.setAllowFileAccess(<span class="literal">true</span>); <span class="comment">// 设置可以访问文件 </span></span><br><span class="line">webSettings.setJavaScriptCanOpenWindowsAutomatically(<span class="literal">true</span>); <span class="comment">// 支持通过JS打开新窗口 </span></span><br><span class="line">webSettings.setLoadsImagesAutomatically(<span class="literal">true</span>); <span class="comment">// 支持自动加载图片</span></span><br><span class="line">webSettings.setDefaultTextEncodingName(<span class="string">&quot;utf-8&quot;</span>);<span class="comment">// 设置编码格式</span></span><br></pre></td></tr></table></figure>

<ul>
<li>WebViewClient类：处理各种通知 &amp; 请求事件</li>
</ul>
<p>onPageStarted()</p>
<p>作用：开始载入页面调用的，我们可以设定一个loading的页面，告诉用户程序在等待网络响应。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">webView.setWebViewClient(<span class="keyword">new</span> <span class="title class_">WebViewClient</span>()&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span>  <span class="title function_">onPageStarted</span><span class="params">(WebView view, String url, Bitmap favicon)</span> &#123;</span><br><span class="line">        <span class="comment">//设定加载开始的操作</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>onPageFinished()</p>
<p>作用：在页面加载结束时调用。我们可以关闭loading 条，切换程序动作。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">webView.setWebViewClient(<span class="keyword">new</span> <span class="title class_">WebViewClient</span>()&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onPageFinished</span><span class="params">(WebView view, String url)</span> &#123;</span><br><span class="line">        <span class="comment">//设定加载结束的操作</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<ul>
<li>WebChromeClient类：辅助 WebView 处理 Javascript 的对话框,网站图标,网站标题等等</li>
</ul>
<p>onProgressChanged（）</p>
<p>作用：获得网页的加载进度并显示</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">webview.setWebChromeClient(<span class="keyword">new</span> <span class="title class_">WebChromeClient</span>()&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onProgressChanged</span><span class="params">(WebView view, <span class="type">int</span> newProgress)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (newProgress &lt; <span class="number">100</span>) &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">progress</span> <span class="operator">=</span> newProgress + <span class="string">&quot;%&quot;</span>;</span><br><span class="line">            progress.setText(progress);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br></pre></td></tr></table></figure>

<h3 id="WebView与JavaScript的交互"><a href="#WebView与JavaScript的交互" class="headerlink" title="WebView与JavaScript的交互"></a>WebView与JavaScript的交互</h3><p>在WebView的开发中，经常需要用到本地函数与H5界面或者Js交互，传递数据等，但是Android本身自带的WebView与Js交互方式存在安全隐患问题，故不详细展开，需要可以看下面的教程链接。</p>
<p>Android与JS通过WebView互相调用方法，实际上是：</p>
<ul>
<li>Android去调用JS的代码</li>
<li>JS去调用Android的代码</li>
</ul>
<p>对于Android调用JS代码的方法有2种：</p>
<ol>
<li>通过<code>WebView</code>的<code>loadUrl（）</code></li>
<li>通过<code>WebView</code>的<code>evaluateJavascript（）</code></li>
</ol>
<p>对于JS调用Android代码的方法有3种：</p>
<ol>
<li>通过<code>WebView</code>的<code>addJavascriptInterface（）</code>进行对象映射</li>
<li>通过 <code>WebViewClient</code> 的<code>shouldOverrideUrlLoading ()</code>方法回调拦截 url</li>
<li>通过 <code>WebChromeClient</code> 的<code>onJsAlert()</code>、<code>onJsConfirm()</code>、<code>onJsPrompt（）</code>方法回调拦截JS对话框<code>alert()</code>、<code>confirm()</code>、<code>prompt（）</code> 消息</li>
</ol>
<p>==参考教程==：<a target="_blank" rel="noopener" href="https://www.jianshu.com/p/345f4d8a5cfa">https://www.jianshu.com/p/345f4d8a5cfa</a></p>
<h3 id="JsBridge实现交互"><a href="#JsBridge实现交互" class="headerlink" title="JsBridge实现交互"></a>JsBridge实现交互</h3><p>为解决Android原生方法的安全隐患问题，推荐使用WebViewJavascriptBridge。</p>
<p>GitHub地址：<a target="_blank" rel="noopener" href="https://github.com/lzyzsd/JsBridge">https://github.com/lzyzsd/JsBridge</a></p>
<p>Android和JS互调（调用相机拍照）</p>
<p>首先是Android写了一个拍照的方法<code>openCamera</code>，使用bridge暴露出去，JS调用该方法，成功后返回给JS<code>success</code>。</p>
<p>拍照完成后Android调用JS暴露的方法<code>picPath</code>将base64字符串传给JS。</p>
<p><img src="https://xiaoshi-blog-img.oss-cn-beijing.aliyuncs.com/img/20211207214944.png" alt="image-20211207214936885"></p>
<h4 id="Android配置"><a href="#Android配置" class="headerlink" title="Android配置"></a>Android配置</h4><p>根目录下的<code>build.gradle</code>（全局的项目构建配置）：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">buildscript &#123;</span><br><span class="line">    repositories &#123;</span><br><span class="line">        google()</span><br><span class="line">        jcenter()</span><br><span class="line">        maven &#123; url <span class="string">&quot;https://jitpack.io&quot;</span> &#125;  <span class="comment">// 添加依赖源,JitPack.io 是一个 GitHub 开源代码库的便捷发布渠道</span></span><br><span class="line">    &#125;</span><br><span class="line">    dependencies &#123;</span><br><span class="line">        classpath <span class="string">&#x27;com.android.tools.build:gradle:3.5.2&#x27;</span></span><br><span class="line">        </span><br><span class="line">        <span class="comment">// <span class="doctag">NOTE:</span> Do not place your application dependencies here; they belong</span></span><br><span class="line">        <span class="comment">// in the individual module build.gradle files</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">allprojects &#123;</span><br><span class="line">    repositories &#123;</span><br><span class="line">        google()</span><br><span class="line">        jcenter()</span><br><span class="line">        maven &#123; url <span class="string">&quot;https://jitpack.io&quot;</span> &#125;  <span class="comment">// 添加依赖源</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>APP目录下的<code>build.gradle</code>（app模块的gradle构建脚本，一般用来管理app包名、版本的以及添加和修改依赖库）：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">dependencies &#123;</span><br><span class="line">    compile <span class="string">&#x27;com.github.lzyzsd:jsbridge:1.0.4&#x27;</span>  <span class="comment">// 添加依赖</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>使用：</p>
<p>xml界面添加组件：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">com.github.lzyzsd.jsbridge.BridgeWebView</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:id</span>=<span class="string">&quot;@+id/activity_jsbridge_bridgewebview&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">&quot;match_parent&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">com.github.lzyzsd.jsbridge.BridgeWebView</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>Activity找到组件：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> BridgeWebView bridgeWebView;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">onCreate</span><span class="params">(Bundle savedInstanceState)</span> &#123;</span><br><span class="line">    <span class="built_in">super</span>.onCreate(savedInstanceState);</span><br><span class="line">    setContentView(R.layout.activity_js_bridge);</span><br><span class="line">    initView();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 初始化View</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">initView</span><span class="params">()</span> &#123;</span><br><span class="line">    bridgeWebView = findViewById(R.id.activity_jsbridge_bridgewebview);</span><br><span class="line">    bridgeWebView.loadUrl(<span class="string">&quot;https://www.cdfgroup.xyz/app/&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// BridgeWebView继承了WebView，所以WebWiew的工具类都可以正常使用</span></span><br><span class="line">    <span class="type">WebSettings</span> <span class="variable">webSettings</span> <span class="operator">=</span> bridgeWebView.getSettings();</span><br><span class="line">    webSettings.setJavaScriptEnabled(<span class="literal">true</span>); <span class="comment">// 开启JavaScript</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 缓存设置</span></span><br><span class="line">    webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); <span class="comment">// 不使用缓存</span></span><br><span class="line">    <span class="comment">// 自适应屏幕设置</span></span><br><span class="line">    webSettings.setUseWideViewPort(<span class="literal">true</span>); <span class="comment">// 将图片调整到适合webview的大小</span></span><br><span class="line">    webSettings.setLoadWithOverviewMode(<span class="literal">true</span>); <span class="comment">// 缩放至屏幕的大小</span></span><br><span class="line">    <span class="comment">// 缩放设置</span></span><br><span class="line">    webSettings.setSupportZoom(<span class="literal">true</span>); <span class="comment">// 支持缩放</span></span><br><span class="line">    webSettings.setBuiltInZoomControls(<span class="literal">true</span>); <span class="comment">// 设置内置的缩放控件</span></span><br><span class="line">    webSettings.setDisplayZoomControls(<span class="literal">false</span>); <span class="comment">// 隐藏原生的缩放控件</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>实现互调：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//注册函数，使JS能通过JSBridge调用Android</span></span><br><span class="line">bridgeWebView.registerHandler(<span class="string">&quot;openCamera&quot;</span>, <span class="keyword">new</span> <span class="title class_">BridgeHandler</span>() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handler</span><span class="params">(String data, CallBackFunction function)</span> &#123;</span><br><span class="line">        <span class="comment">//JS传递给Android</span></span><br><span class="line">        Toast.makeText(JsBridgeActivity.<span class="built_in">this</span>, data, Toast.LENGTH_LONG).show();</span><br><span class="line">        takePhoto();  <span class="comment">// 拍照</span></span><br><span class="line">        <span class="comment">//Android返回给JS的消息</span></span><br><span class="line">        function.onCallBack(<span class="string">&quot;success&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// Android调用JS的方法（这里放在takePhoto()方法里面）</span></span><br><span class="line">bridgeWebView.callHandler(<span class="string">&quot;picPath&quot;</span>, pic64, <span class="keyword">new</span> <span class="title class_">CallBackFunction</span>() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onCallBack</span><span class="params">(String data)</span> &#123;</span><br><span class="line">        Toast.makeText(JsBridgeActivity.<span class="built_in">this</span>, data, Toast.LENGTH_LONG).show();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<h4 id="JS配置"><a href="#JS配置" class="headerlink" title="JS配置"></a>JS配置</h4><p>JS需要封装一个工具类<code>jsBridge</code>（参考：<a target="_blank" rel="noopener" href="https://www.jianshu.com/p/b03eaa6fb38a">JSbridge 在Vue的封装与交互</a>）：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> isAndroid = navigator.<span class="property">userAgent</span>.<span class="title function_">indexOf</span>(<span class="string">&#x27;Android&#x27;</span>) &gt; -<span class="number">1</span> || navigator.<span class="property">userAgent</span>.<span class="title function_">indexOf</span>(<span class="string">&#x27;Adr&#x27;</span>) &gt; -<span class="number">1</span>;</span><br><span class="line"><span class="keyword">let</span> isiOS = !!navigator.<span class="property">userAgent</span>.<span class="title function_">match</span>(<span class="regexp">/\(i[^;]+;( U;)? CPU.+Mac OS X/</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//执行回调函数 这是必须要写的，用来创建一些设置</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">setupWebViewJavascriptBridge</span>(<span class="params">callback</span>) &#123;</span><br><span class="line">  <span class="comment">//Android使用</span></span><br><span class="line">  <span class="keyword">if</span> (isAndroid) &#123;</span><br><span class="line">    <span class="comment">//如果该对象已存在则直接执行</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="variable language_">window</span>.<span class="property">WebViewJavascriptBridge</span>) &#123;</span><br><span class="line">      <span class="title function_">callback</span>(<span class="variable language_">window</span>.<span class="property">WebViewJavascriptBridge</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="comment">//否则添加事件监听再执行</span></span><br><span class="line">      <span class="variable language_">document</span>.<span class="title function_">addEventListener</span>(</span><br><span class="line">        <span class="string">&#x27;WebViewJavascriptBridgeReady&#x27;</span>,</span><br><span class="line">        <span class="function">() =&gt;</span> &#123;</span><br><span class="line">          <span class="title function_">callback</span>(<span class="variable language_">window</span>.<span class="property">WebViewJavascriptBridge</span>);</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="literal">false</span></span><br><span class="line">      );</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;tag，android&#x27;</span>);</span><br><span class="line">    sessionStorage.<span class="property">phoneType</span> = <span class="string">&#x27;android&#x27;</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//iOS使用</span></span><br><span class="line">  <span class="keyword">if</span> (isiOS) &#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="variable language_">window</span>.<span class="property">WebViewJavascriptBridge</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">callback</span>(<span class="variable language_">window</span>.<span class="property">WebViewJavascriptBridge</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (<span class="variable language_">window</span>.<span class="property">WVJBCallbacks</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="variable language_">window</span>.<span class="property">WVJBCallbacks</span>.<span class="title function_">push</span>(callback);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="variable language_">window</span>.<span class="property">WVJBCallbacks</span> = [callback];</span><br><span class="line">    <span class="keyword">var</span> <span class="title class_">WVJBIframe</span> = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;iframe&#x27;</span>);</span><br><span class="line">    <span class="title class_">WVJBIframe</span>.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;none&#x27;</span>;</span><br><span class="line">    <span class="title class_">WVJBIframe</span>.<span class="property">src</span> = <span class="string">&#x27;wvjbscheme://__BRIDGE_LOADED__&#x27;</span>;</span><br><span class="line">    <span class="variable language_">document</span>.<span class="property">documentElement</span>.<span class="title function_">appendChild</span>(<span class="title class_">WVJBIframe</span>);</span><br><span class="line">    <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">      <span class="variable language_">document</span>.<span class="property">documentElement</span>.<span class="title function_">removeChild</span>(<span class="title class_">WVJBIframe</span>);</span><br><span class="line">    &#125;, <span class="number">0</span>);</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;tag&#x27;</span>, <span class="string">&#x27;ios&#x27;</span>);</span><br><span class="line">    sessionStorage.<span class="property">phoneType</span> = <span class="string">&#x27;ios&#x27;</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//注册回调函数，第一次连接时调用(进入H5页面) 初始化函数(android需要初始化,ios不用)</span></span><br><span class="line"><span class="title function_">setupWebViewJavascriptBridge</span>(<span class="function">(<span class="params">bridge</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;tag，setupWebViewJavascriptBridge&#x27;</span>);</span><br><span class="line">  <span class="keyword">if</span> (isAndroid) &#123;</span><br><span class="line">    <span class="comment">//初始化 一个无参数的handler供Android调用</span></span><br><span class="line">    bridge.<span class="title function_">init</span>(<span class="function">(<span class="params">message, responseCallback</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;JS got a message&#x27;</span>, message);</span><br><span class="line">      <span class="keyword">var</span> data = &#123;</span><br><span class="line">        <span class="string">&#x27;Javascript Responds&#x27;</span>: <span class="string">&#x27;Wee!&#x27;</span></span><br><span class="line">      &#125;;</span><br><span class="line">      <span class="title function_">responseCallback</span>(data);</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="comment">// js调APP方法 （参数分别为:app提供的方法名  传给app的数据  回调）</span></span><br><span class="line">  <span class="title function_">callHandler</span>(<span class="params">name, data, callback</span>) &#123;</span><br><span class="line">    <span class="title function_">setupWebViewJavascriptBridge</span>(<span class="function">(<span class="params">bridge</span>) =&gt;</span> &#123;</span><br><span class="line">      bridge.<span class="title function_">callHandler</span>(name, data, callback);</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// APP调js方法 （参数分别为:js提供的方法名  回调）</span></span><br><span class="line">  <span class="title function_">registerHandler</span>(<span class="params">name, callback</span>) &#123;</span><br><span class="line">    <span class="title function_">setupWebViewJavascriptBridge</span>(<span class="function">(<span class="params">bridge</span>) =&gt;</span> &#123;</span><br><span class="line">      bridge.<span class="title function_">registerHandler</span>(name, <span class="function">(<span class="params">data, responseCallback</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="title function_">callback</span>(data, responseCallback);</span><br><span class="line">      &#125;);</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>之后在<code>main.js</code>中引入：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> jsBridge <span class="keyword">from</span> <span class="string">&#x27;./utils/jsBridge.js&#x27;</span>  <span class="comment">// h5和安卓原生联调</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$bridge</span> = jsBridge;</span><br></pre></td></tr></table></figure>

<p>使用：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 调用Android的方法(JS调用Android)</span></span><br><span class="line"><span class="title function_">chooseImage</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;调用拍照&quot;</span>);</span><br><span class="line">  <span class="variable language_">this</span>.<span class="property">$bridge</span>.<span class="title function_">callHandler</span>(</span><br><span class="line">    <span class="string">&#x27;openCamera&#x27;</span></span><br><span class="line">    , &#123;<span class="string">&#x27;param&#x27;</span>: <span class="string">&quot;hello,android!&quot;</span>&#125;</span><br><span class="line">    , <span class="function">(<span class="params">responseData</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;JS接收到：&quot;</span> + responseData);</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;,</span><br><span class="line"></span><br><span class="line"><span class="comment">// 注册接收图片路径的回调方法(Android调用JS)</span></span><br><span class="line"><span class="title function_">registerPicResultFunction</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="variable language_">this</span>.<span class="property">$bridge</span>.<span class="title function_">registerHandler</span>(<span class="string">&quot;picPath&quot;</span>, <span class="function">(<span class="params">data, responseCallback</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;JS接收到图片的base64编码：&quot;</span>);</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(data);</span><br><span class="line">    <span class="keyword">let</span> base64 = data.<span class="title function_">replace</span>(<span class="regexp">/\+/g</span>, <span class="string">&quot;%2B&quot;</span>);  <span class="comment">// 加上这个保证上传的图片下载进来是正确的</span></span><br><span class="line">    <span class="comment">// 获得安卓的图片路径</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">picList</span>.<span class="title function_">push</span>(&#123;<span class="attr">url</span>: <span class="string">&quot;data:image/png;base64,&quot;</span> + base64&#125;);</span><br><span class="line">    <span class="comment">// 接收成功并返回值给安卓</span></span><br><span class="line">    <span class="title function_">responseCallback</span>(<span class="string">&quot;success&quot;</span>);</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure>

<h3 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h3><p>在开发中比较麻烦的问题就是调试了。比如写了一个地图定位程序，JS需要调用Android原生的定位方法。</p>
<ol>
<li><p>写一个Android获取当前定位信息的接口</p>
</li>
<li><p>JS调用后显示当前位置在地图上</p>
</li>
</ol>
<p>当JS还需要依赖该定位数据写一些复杂的逻辑时，调试很麻烦。</p>
<ol>
<li>JS程序逻辑编写</li>
<li>JS程序打包</li>
<li>Android更新打包后的JS程序</li>
<li>Android Studio连接手机进行调试，观察控制台输出数据</li>
</ol>
<p>发现问题后修改代码还得执行一次这个流程，真的心累。</p>
<p>目前尚未找到合适的解决方案。</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  


  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="XiaoShi"
      src="/xiaoshihd/images/xiaoshi.png">
  <p class="site-author-name" itemprop="name">XiaoShi</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/xiaoshihd/archives/">
        
          <span class="site-state-item-count">2</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/xiaoshihd/categories/">
          
        <span class="site-state-item-count">2</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/xiaoshihd/tags/">
          
        <span class="site-state-item-count">3</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/xiaoshi-hd" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;xiaoshi-hd" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">XiaoShi</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://muse.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/xiaoshihd/lib/anime.min.js"></script>
  <script src="/xiaoshihd/lib/velocity/velocity.min.js"></script>
  <script src="/xiaoshihd/lib/velocity/velocity.ui.min.js"></script>

<script src="/xiaoshihd/js/utils.js"></script>

<script src="/xiaoshihd/js/motion.js"></script>


<script src="/xiaoshihd/js/schemes/muse.js"></script>


<script src="/xiaoshihd/js/next-boot.js"></script>




  




  
<script src="/xiaoshihd/js/local-search.js"></script>













  

  
<script src="https://cdn.jsdelivr.net/npm/darkmode-js@1.5.7/lib/darkmode-js.min.js"></script>

<script>
var options = {
  bottom: '64px',
  right: 'unset',
  left: '32px',
  time: '0.5s',
  mixColor: 'transparent',
  backgroundColor: 'transparent',
  buttonColorDark: '#100f2c',
  buttonColorLight: '#fff',
  saveInCookies: true,
  label: '🌓',
  autoMatchOsTheme: true
}
const darkmode = new Darkmode(options);
window.darkmode = darkmode;
darkmode.showWidget();
</script>

</body>
</html>
